summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.fixtures.yml1
-rw-r--r--.gitattributes5
-rw-r--r--.gitignore8
-rw-r--r--.rspec4
-rw-r--r--.rubocop.yml508
-rw-r--r--.sync.yml23
-rw-r--r--.travis.yml39
-rw-r--r--CHANGELOG.md239
-rw-r--r--CONTRIBUTING.md12
-rw-r--r--Gemfile92
-rw-r--r--LICENSE209
-rw-r--r--NOTICE23
-rw-r--r--README.markdown1702
-rw-r--r--Rakefile44
-rw-r--r--examples/file_line.pp (renamed from tests/file_line.pp)4
-rw-r--r--examples/has_interface_with.pp (renamed from tests/has_interface_with.pp)3
-rw-r--r--examples/has_ip_address.pp (renamed from tests/has_ip_address.pp)2
-rw-r--r--examples/has_ip_network.pp (renamed from tests/has_ip_network.pp)3
-rw-r--r--examples/init.pp1
-rw-r--r--lib/facter/facter_dot_d.rb10
-rw-r--r--lib/facter/package_provider.rb21
-rw-r--r--lib/facter/pe_version.rb9
-rw-r--r--lib/facter/puppet_settings.rb43
-rw-r--r--lib/facter/puppet_vardir.rb26
-rw-r--r--lib/facter/root_home.rb13
-rw-r--r--lib/facter/service_provider.rb17
-rw-r--r--lib/puppet/functions/deprecation.rb29
-rw-r--r--lib/puppet/functions/is_a.rb32
-rw-r--r--lib/puppet/functions/is_absolute_path.rb15
-rw-r--r--lib/puppet/functions/is_array.rb15
-rw-r--r--lib/puppet/functions/is_bool.rb15
-rw-r--r--lib/puppet/functions/is_float.rb15
-rw-r--r--lib/puppet/functions/is_ip_address.rb15
-rw-r--r--lib/puppet/functions/is_ipv4_address.rb15
-rw-r--r--lib/puppet/functions/is_ipv6_address.rb15
-rw-r--r--lib/puppet/functions/is_numeric.rb15
-rw-r--r--lib/puppet/functions/is_string.rb15
-rw-r--r--lib/puppet/functions/type_of.rb2
-rw-r--r--lib/puppet/functions/validate_absolute_path.rb15
-rw-r--r--lib/puppet/functions/validate_array.rb15
-rw-r--r--lib/puppet/functions/validate_bool.rb15
-rw-r--r--lib/puppet/functions/validate_hash.rb15
-rw-r--r--lib/puppet/functions/validate_integer.rb15
-rw-r--r--lib/puppet/functions/validate_ip_address.rb15
-rw-r--r--lib/puppet/functions/validate_ipv4_address.rb15
-rw-r--r--lib/puppet/functions/validate_ipv6_address.rb15
-rw-r--r--lib/puppet/functions/validate_legacy.rb62
-rw-r--r--lib/puppet/functions/validate_numeric.rb15
-rw-r--r--lib/puppet/functions/validate_re.rb15
-rw-r--r--lib/puppet/functions/validate_slength.rb15
-rw-r--r--lib/puppet/functions/validate_string.rb15
-rw-r--r--lib/puppet/parser/functions/any2bool.rb55
-rw-r--r--lib/puppet/parser/functions/assert_private.rb29
-rw-r--r--lib/puppet/parser/functions/base64.rb41
-rw-r--r--lib/puppet/parser/functions/bool2str.rb26
-rw-r--r--lib/puppet/parser/functions/ceiling.rb25
-rw-r--r--lib/puppet/parser/functions/clamp.rb30
-rw-r--r--lib/puppet/parser/functions/concat.rb2
-rw-r--r--lib/puppet/parser/functions/convert_base.rb35
-rw-r--r--lib/puppet/parser/functions/defined_with_params.rb5
-rw-r--r--lib/puppet/parser/functions/delete.rb8
-rw-r--r--lib/puppet/parser/functions/delete_regex.rb45
-rw-r--r--lib/puppet/parser/functions/deprecation.rb17
-rw-r--r--lib/puppet/parser/functions/dig.rb16
-rw-r--r--lib/puppet/parser/functions/dig44.rb73
-rw-r--r--lib/puppet/parser/functions/dirname.rb14
-rw-r--r--lib/puppet/parser/functions/dos2unix.rb15
-rw-r--r--lib/puppet/parser/functions/empty.rb12
-rw-r--r--lib/puppet/parser/functions/enclose_ipv6.rb45
-rw-r--r--lib/puppet/parser/functions/ensure_packages.rb27
-rw-r--r--lib/puppet/parser/functions/ensure_resources.rb54
-rw-r--r--lib/puppet/parser/functions/fqdn_rand_string.rb34
-rw-r--r--lib/puppet/parser/functions/fqdn_rotate.rb38
-rw-r--r--lib/puppet/parser/functions/fqdn_uuid.rb92
-rw-r--r--lib/puppet/parser/functions/getparam.rb2
-rw-r--r--lib/puppet/parser/functions/getvar.rb8
-rw-r--r--lib/puppet/parser/functions/has_interface_with.rb7
-rw-r--r--lib/puppet/parser/functions/hash.rb2
-rw-r--r--lib/puppet/parser/functions/intersection.rb6
-rw-r--r--lib/puppet/parser/functions/is_absolute_path.rb50
-rw-r--r--lib/puppet/parser/functions/is_array.rb4
-rw-r--r--lib/puppet/parser/functions/is_bool.rb4
-rw-r--r--lib/puppet/parser/functions/is_domain_name.rb12
-rw-r--r--lib/puppet/parser/functions/is_email_address.rb21
-rw-r--r--lib/puppet/parser/functions/is_float.rb2
-rw-r--r--lib/puppet/parser/functions/is_integer.rb2
-rw-r--r--lib/puppet/parser/functions/is_ip_address.rb2
-rw-r--r--lib/puppet/parser/functions/is_ipv4_address.rb30
-rw-r--r--lib/puppet/parser/functions/is_ipv6_address.rb30
-rw-r--r--lib/puppet/parser/functions/is_mac_address.rb2
-rw-r--r--lib/puppet/parser/functions/is_numeric.rb4
-rw-r--r--lib/puppet/parser/functions/is_string.rb5
-rw-r--r--lib/puppet/parser/functions/join_keys_to_values.rb15
-rw-r--r--lib/puppet/parser/functions/load_module_metadata.rb24
-rw-r--r--lib/puppet/parser/functions/loadjson.rb34
-rw-r--r--lib/puppet/parser/functions/loadyaml.rb34
-rw-r--r--lib/puppet/parser/functions/member.rb2
-rw-r--r--lib/puppet/parser/functions/parsejson.rb25
-rw-r--r--lib/puppet/parser/functions/parseyaml.rb25
-rw-r--r--lib/puppet/parser/functions/prefix.rb23
-rw-r--r--lib/puppet/parser/functions/private.rb24
-rw-r--r--lib/puppet/parser/functions/pry.rb30
-rw-r--r--lib/puppet/parser/functions/pw_hash.rb56
-rw-r--r--lib/puppet/parser/functions/range.rb25
-rw-r--r--lib/puppet/parser/functions/regexpescape.rb31
-rw-r--r--lib/puppet/parser/functions/seeded_rand.rb22
-rw-r--r--lib/puppet/parser/functions/shell_escape.rb30
-rw-r--r--lib/puppet/parser/functions/shell_join.rb31
-rw-r--r--lib/puppet/parser/functions/shell_split.rb26
-rw-r--r--lib/puppet/parser/functions/size.rb8
-rw-r--r--lib/puppet/parser/functions/str2bool.rb10
-rw-r--r--lib/puppet/parser/functions/suffix.rb24
-rw-r--r--lib/puppet/parser/functions/time.rb5
-rw-r--r--lib/puppet/parser/functions/try_get_value.rb53
-rw-r--r--lib/puppet/parser/functions/union.rb17
-rw-r--r--lib/puppet/parser/functions/unix2dos.rb15
-rw-r--r--lib/puppet/parser/functions/upcase.rb19
-rw-r--r--lib/puppet/parser/functions/uriescape.rb2
-rw-r--r--lib/puppet/parser/functions/validate_absolute_path.rb27
-rw-r--r--lib/puppet/parser/functions/validate_array.rb2
-rw-r--r--lib/puppet/parser/functions/validate_augeas.rb2
-rw-r--r--lib/puppet/parser/functions/validate_bool.rb3
-rw-r--r--lib/puppet/parser/functions/validate_cmd.rb2
-rw-r--r--lib/puppet/parser/functions/validate_email_address.rb31
-rw-r--r--lib/puppet/parser/functions/validate_hash.rb2
-rw-r--r--lib/puppet/parser/functions/validate_integer.rb134
-rw-r--r--lib/puppet/parser/functions/validate_ip_address.rb52
-rw-r--r--lib/puppet/parser/functions/validate_ipv4_address.rb4
-rw-r--r--lib/puppet/parser/functions/validate_ipv6_address.rb2
-rw-r--r--lib/puppet/parser/functions/validate_numeric.rb96
-rw-r--r--lib/puppet/parser/functions/validate_re.rb14
-rw-r--r--lib/puppet/parser/functions/validate_slength.rb8
-rw-r--r--lib/puppet/parser/functions/validate_string.rb11
-rw-r--r--lib/puppet/parser/functions/validate_x509_rsa_key_pair.rb47
-rw-r--r--lib/puppet/provider/file_line/ruby.rb99
-rw-r--r--lib/puppet/type/file_line.rb76
-rw-r--r--manifests/init.pp4
-rw-r--r--manifests/stages.pp2
-rw-r--r--metadata.json19
-rwxr-xr-xspec/acceptance/anchor_spec.rb26
-rwxr-xr-xspec/acceptance/ceiling_spec.rb39
-rwxr-xr-xspec/acceptance/clamp_spec.rb40
-rwxr-xr-xspec/acceptance/concat_spec.rb14
-rw-r--r--spec/acceptance/deprecation_spec.rb102
-rwxr-xr-xspec/acceptance/empty_spec.rb14
-rwxr-xr-xspec/acceptance/ensure_packages_spec.rb22
-rwxr-xr-xspec/acceptance/ensure_resource_spec.rb20
-rw-r--r--spec/acceptance/fqdn_rand_string_spec.rb66
-rwxr-xr-xspec/acceptance/fqdn_rotate_spec.rb79
-rw-r--r--spec/acceptance/is_a_spec.rb30
-rwxr-xr-xspec/acceptance/is_ipv4_address_spec.rb52
-rwxr-xr-xspec/acceptance/is_ipv6_address_spec.rb66
-rwxr-xr-xspec/acceptance/is_string_spec.rb11
-rw-r--r--spec/acceptance/loadjson_spec.rb52
-rw-r--r--spec/acceptance/loadyaml_spec.rb23
-rw-r--r--spec/acceptance/nodesets/centos-59-x64.yml10
-rw-r--r--spec/acceptance/nodesets/centos-6-vcloud.yml15
-rw-r--r--spec/acceptance/nodesets/centos-64-x64-pe.yml12
-rw-r--r--spec/acceptance/nodesets/centos-64-x64.yml10
-rw-r--r--spec/acceptance/nodesets/centos-65-x64.yml10
-rw-r--r--spec/acceptance/nodesets/centos-7-x64.yml10
-rw-r--r--spec/acceptance/nodesets/debian-8-x64.yml10
-rw-r--r--spec/acceptance/nodesets/default.yml12
-rw-r--r--spec/acceptance/nodesets/docker/centos-7.yml12
-rw-r--r--spec/acceptance/nodesets/docker/debian-8.yml11
-rw-r--r--spec/acceptance/nodesets/docker/ubuntu-14.04.yml12
-rw-r--r--spec/acceptance/nodesets/fedora-18-x64.yml10
-rw-r--r--spec/acceptance/nodesets/sles-11-x64.yml10
-rw-r--r--spec/acceptance/nodesets/ubuntu-server-10044-x64.yml10
-rw-r--r--spec/acceptance/nodesets/ubuntu-server-12042-x64.yml10
-rw-r--r--spec/acceptance/nodesets/ubuntu-server-1404-x64.yml11
-rw-r--r--spec/acceptance/nodesets/windows-2003-i386.yml26
-rw-r--r--spec/acceptance/nodesets/windows-2003-x86_64.yml26
-rw-r--r--spec/acceptance/nodesets/windows-2008-x86_64.yml26
-rw-r--r--spec/acceptance/nodesets/windows-2008r2-x86_64.yml26
-rw-r--r--spec/acceptance/nodesets/windows-2012-x86_64.yml26
-rw-r--r--spec/acceptance/nodesets/windows-2012r2-x86_64.yml26
-rwxr-xr-xspec/acceptance/parsejson_spec.rb23
-rwxr-xr-xspec/acceptance/parseyaml_spec.rb25
-rw-r--r--spec/acceptance/pw_hash_spec.rb34
-rwxr-xr-xspec/acceptance/try_get_value_spec.rb47
-rwxr-xr-xspec/acceptance/union_spec.rb5
-rwxr-xr-xspec/acceptance/validate_array_spec.rb16
-rwxr-xr-xspec/acceptance/validate_bool_spec.rb16
-rwxr-xr-xspec/acceptance/validate_hash_spec.rb16
-rwxr-xr-xspec/acceptance/validate_string_spec.rb7
-rw-r--r--spec/aliases/absolute_path_spec.rb62
-rw-r--r--spec/aliases/absolutepath_spec.rb49
-rw-r--r--spec/aliases/array_spec.rb34
-rw-r--r--spec/aliases/bool_spec.rb32
-rw-r--r--spec/aliases/float_spec.rb28
-rw-r--r--spec/aliases/httpsurl_spec.rb40
-rw-r--r--spec/aliases/httpurl_spec.rb43
-rw-r--r--spec/aliases/integer_spec.rb28
-rw-r--r--spec/aliases/ip_address.rb34
-rw-r--r--spec/aliases/ipv4_spec.rb22
-rw-r--r--spec/aliases/ipv6_spec.rb30
-rw-r--r--spec/aliases/numeric_spec.rb32
-rw-r--r--spec/aliases/string_spec.rb32
-rw-r--r--spec/aliases/unixpath_spec.rb41
-rw-r--r--spec/aliases/windowspath_spec.rb44
-rwxr-xr-xspec/classes/anchor_spec.rb30
-rw-r--r--spec/fixtures/lsuser/root2
-rw-r--r--spec/fixtures/test/manifests/absolute_path.pp6
-rw-r--r--spec/fixtures/test/manifests/absolutepath.pp6
-rw-r--r--spec/fixtures/test/manifests/array.pp8
-rw-r--r--spec/fixtures/test/manifests/bool.pp8
-rw-r--r--spec/fixtures/test/manifests/ensure_resources.pp4
-rw-r--r--spec/fixtures/test/manifests/float.pp8
-rw-r--r--spec/fixtures/test/manifests/httpsurl.pp6
-rw-r--r--spec/fixtures/test/manifests/httpurl.pp6
-rw-r--r--spec/fixtures/test/manifests/integer.pp8
-rw-r--r--spec/fixtures/test/manifests/ip_address.pp6
-rw-r--r--spec/fixtures/test/manifests/ipv4.pp6
-rw-r--r--spec/fixtures/test/manifests/ipv6.pp6
-rw-r--r--spec/fixtures/test/manifests/numeric.pp8
-rw-r--r--spec/fixtures/test/manifests/string.pp8
-rw-r--r--spec/fixtures/test/manifests/unixpath.pp6
-rw-r--r--spec/fixtures/test/manifests/windowspath.pp6
-rwxr-xr-xspec/functions/abs_spec.rb39
-rwxr-xr-xspec/functions/any2array_spec.rb64
-rwxr-xr-xspec/functions/any2bool_spec.rb42
-rwxr-xr-xspec/functions/assert_private_spec.rb41
-rwxr-xr-xspec/functions/base64_spec.rb65
-rwxr-xr-xspec/functions/basename_spec.rb14
-rwxr-xr-xspec/functions/bool2num_spec.rb38
-rwxr-xr-xspec/functions/bool2str_spec.rb17
-rwxr-xr-xspec/functions/camelcase_spec.rb17
-rwxr-xr-xspec/functions/capitalize_spec.rb37
-rwxr-xr-xspec/functions/ceiling_spec.rb13
-rwxr-xr-xspec/functions/chomp_spec.rb40
-rwxr-xr-xspec/functions/chop_spec.rb40
-rw-r--r--spec/functions/clamp_spec.rb16
-rwxr-xr-xspec/functions/concat_spec.rb63
-rw-r--r--spec/functions/convert_base_spec.rb24
-rwxr-xr-xspec/functions/count_spec.rb43
-rwxr-xr-xspec/functions/deep_merge_spec.rb144
-rwxr-xr-xspec/functions/defined_with_params_spec.rb36
-rwxr-xr-xspec/functions/delete_at_spec.rb37
-rwxr-xr-xspec/functions/delete_regex_spec.rb54
-rwxr-xr-xspec/functions/delete_spec.rb105
-rwxr-xr-xspec/functions/delete_undef_values_spec.rb85
-rwxr-xr-xspec/functions/delete_values_spec.rb57
-rw-r--r--spec/functions/deprecation_spec.rb60
-rwxr-xr-xspec/functions/difference_spec.rb34
-rw-r--r--spec/functions/dig44_spec.rb105
-rw-r--r--spec/functions/dig_spec.rb13
-rwxr-xr-xspec/functions/dirname_spec.rb31
-rw-r--r--spec/functions/dos2unix_spec.rb40
-rwxr-xr-xspec/functions/downcase_spec.rb42
-rwxr-xr-xspec/functions/empty_spec.rb42
-rwxr-xr-xspec/functions/ensure_packages_spec.rb95
-rwxr-xr-xspec/functions/ensure_resource_spec.rb148
-rwxr-xr-xspec/functions/flatten_spec.rb35
-rwxr-xr-xspec/functions/floor_spec.rb45
-rw-r--r--spec/functions/fqdn_rand_string_spec.rb65
-rwxr-xr-xspec/functions/fqdn_rotate_spec.rb80
-rw-r--r--spec/functions/fqdn_uuid_spec.rb14
-rwxr-xr-xspec/functions/get_module_path_spec.rb56
-rwxr-xr-xspec/functions/getparam_spec.rb87
-rwxr-xr-xspec/functions/getvar_spec.rb46
-rwxr-xr-xspec/functions/grep_spec.rb32
-rwxr-xr-xspec/functions/has_interface_with_spec.rb80
-rwxr-xr-xspec/functions/has_ip_address_spec.rb45
-rwxr-xr-xspec/functions/has_ip_network_spec.rb42
-rwxr-xr-xspec/functions/has_key_spec.rb51
-rwxr-xr-xspec/functions/hash_spec.rb27
-rwxr-xr-xspec/functions/intersection_spec.rb34
-rw-r--r--spec/functions/is_a_spec.rb25
-rwxr-xr-xspec/functions/is_array_spec.rb57
-rwxr-xr-xspec/functions/is_bool_spec.rb71
-rwxr-xr-xspec/functions/is_domain_name_spec.rb99
-rwxr-xr-xspec/functions/is_email_address_spec.rb14
-rwxr-xr-xspec/functions/is_float_spec.rb53
-rwxr-xr-xspec/functions/is_function_available.rb34
-rwxr-xr-xspec/functions/is_hash_spec.rb34
-rwxr-xr-xspec/functions/is_integer_spec.rb106
-rwxr-xr-xspec/functions/is_ip_address_spec.rb71
-rw-r--r--spec/functions/is_ipv4_address_spec.rb32
-rw-r--r--spec/functions/is_ipv6_address_spec.rb30
-rwxr-xr-xspec/functions/is_mac_address_spec.rb47
-rwxr-xr-xspec/functions/is_numeric_spec.rb157
-rwxr-xr-xspec/functions/is_string_spec.rb63
-rwxr-xr-xspec/functions/join_keys_to_values_spec.rb55
-rwxr-xr-xspec/functions/join_spec.rb30
-rwxr-xr-xspec/functions/keys_spec.rb32
-rwxr-xr-xspec/functions/load_module_metadata_spec.rb38
-rw-r--r--spec/functions/loadjson_spec.rb49
-rwxr-xr-xspec/functions/loadyaml_spec.rb41
-rwxr-xr-xspec/functions/lstrip_spec.rb56
-rwxr-xr-xspec/functions/max_spec.rb38
-rwxr-xr-xspec/functions/member_spec.rb49
-rwxr-xr-xspec/functions/merge_spec.rb69
-rwxr-xr-xspec/functions/min_spec.rb38
-rwxr-xr-xspec/functions/num2bool_spec.rb83
-rwxr-xr-xspec/functions/parsejson_spec.rb68
-rwxr-xr-xspec/functions/parseyaml_spec.rb87
-rwxr-xr-xspec/functions/pick_default_spec.rb74
-rwxr-xr-xspec/functions/pick_spec.rb40
-rwxr-xr-xspec/functions/prefix_spec.rb50
-rw-r--r--[-rwxr-xr-x]spec/functions/private_spec.rb15
-rw-r--r--spec/functions/pw_hash_spec.rb69
-rwxr-xr-xspec/functions/range_spec.rb164
-rw-r--r--spec/functions/regexpescape_spec.rb36
-rwxr-xr-xspec/functions/reject_spec.rb31
-rwxr-xr-xspec/functions/reverse_spec.rb45
-rwxr-xr-xspec/functions/rstrip_spec.rb61
-rw-r--r--spec/functions/seeded_rand_spec.rb53
-rw-r--r--spec/functions/shell_escape_spec.rb22
-rw-r--r--spec/functions/shell_join_spec.rb23
-rw-r--r--spec/functions/shell_split_spec.rb24
-rwxr-xr-xspec/functions/shuffle_spec.rb48
-rwxr-xr-xspec/functions/size_spec.rb45
-rwxr-xr-xspec/functions/sort_spec.rb32
-rwxr-xr-xspec/functions/squeeze_spec.rb50
-rwxr-xr-xspec/functions/str2bool_spec.rb40
-rwxr-xr-xspec/functions/str2saltedsha512_spec.rb50
-rwxr-xr-xspec/functions/strftime_spec.rb5
-rwxr-xr-xspec/functions/strip_spec.rb55
-rwxr-xr-xspec/functions/suffix_spec.rb59
-rwxr-xr-xspec/functions/swapcase_spec.rb54
-rwxr-xr-xspec/functions/time_spec.rb40
-rwxr-xr-xspec/functions/to_bytes_spec.rb147
-rw-r--r--spec/functions/try_get_value_spec.rb100
-rw-r--r--spec/functions/type3x_spec.rb4
-rw-r--r--spec/functions/type_of_spec.rb25
-rwxr-xr-xspec/functions/type_spec.rb4
-rwxr-xr-xspec/functions/union_spec.rb33
-rwxr-xr-xspec/functions/unique_spec.rb44
-rw-r--r--spec/functions/unix2dos_spec.rb40
-rwxr-xr-xspec/functions/upcase_spec.rb39
-rwxr-xr-xspec/functions/uriescape_spec.rb49
-rwxr-xr-xspec/functions/validate_absolute_path_spec.rb127
-rwxr-xr-xspec/functions/validate_array_spec.rb55
-rwxr-xr-xspec/functions/validate_augeas_spec.rb70
-rwxr-xr-xspec/functions/validate_bool_spec.rb71
-rwxr-xr-xspec/functions/validate_cmd_spec.rb104
-rw-r--r--spec/functions/validate_email_address_spec.rb23
-rwxr-xr-xspec/functions/validate_hash_spec.rb57
-rwxr-xr-xspec/functions/validate_integer_spec.rb101
-rw-r--r--spec/functions/validate_ip_address_spec.rb65
-rwxr-xr-xspec/functions/validate_ipv4_address_spec.rb81
-rwxr-xr-xspec/functions/validate_ipv6_address_spec.rb97
-rw-r--r--spec/functions/validate_legacy_spec.rb68
-rwxr-xr-xspec/functions/validate_numeric_spec.rb100
-rwxr-xr-xspec/functions/validate_re_spec.rb109
-rwxr-xr-xspec/functions/validate_slength_spec.rb103
-rwxr-xr-xspec/functions/validate_string_spec.rb75
-rwxr-xr-xspec/functions/validate_x509_rsa_key_pair_spec.rb180
-rwxr-xr-xspec/functions/values_at_spec.rb71
-rwxr-xr-xspec/functions/values_spec.rb42
-rwxr-xr-xspec/functions/zip_spec.rb40
-rwxr-xr-xspec/lib/puppet_spec/compiler.rb47
-rwxr-xr-xspec/lib/puppet_spec/database.rb30
-rwxr-xr-xspec/lib/puppet_spec/files.rb61
-rwxr-xr-xspec/lib/puppet_spec/fixtures.rb29
-rwxr-xr-xspec/lib/puppet_spec/matchers.rb121
-rwxr-xr-xspec/lib/puppet_spec/modules.rb27
-rwxr-xr-xspec/lib/puppet_spec/pops.rb17
-rwxr-xr-xspec/lib/puppet_spec/scope.rb15
-rwxr-xr-xspec/lib/puppet_spec/settings.rb16
-rwxr-xr-xspec/lib/puppet_spec/verbose.rb10
-rw-r--r--spec/spec.opts6
-rwxr-xr-xspec/spec_helper.rb36
-rwxr-xr-xspec/spec_helper_acceptance.rb64
-rw-r--r--spec/spec_helper_local.rb31
-rw-r--r--spec/support/shared_data.rb38
-rw-r--r--spec/unit/ensure_resources_spec.rb22
-rw-r--r--spec/unit/facter/package_provider_spec.rb44
-rwxr-xr-xspec/unit/facter/pe_version_spec.rb12
-rwxr-xr-xspec/unit/facter/root_home_spec.rb13
-rw-r--r--spec/unit/facter/service_provider_spec.rb37
-rwxr-xr-xspec/unit/facter/util/puppet_settings_spec.rb1
-rw-r--r--spec/unit/puppet/functions/type_of_spec.rb33
-rwxr-xr-xspec/unit/puppet/parser/functions/basename_spec.rb46
-rwxr-xr-xspec/unit/puppet/parser/functions/bool2str_spec.rb46
-rwxr-xr-xspec/unit/puppet/parser/functions/camelcase_spec.rb24
-rw-r--r--spec/unit/puppet/parser/functions/enclose_ipv6_spec.rb69
-rw-r--r--spec/unit/puppet/parser/functions/is_absolute_path_spec.rb86
-rwxr-xr-xspec/unit/puppet/provider/file_line/ruby_spec.rb260
-rwxr-xr-xspec/unit/puppet/type/file_line_spec.rb10
-rw-r--r--tests/init.pp1
-rw-r--r--types/absolutepath.pp2
-rw-r--r--types/compat/absolute_path.pp7
-rw-r--r--types/compat/array.pp2
-rw-r--r--types/compat/bool.pp2
-rw-r--r--types/compat/float.pp19
-rw-r--r--types/compat/integer.pp23
-rw-r--r--types/compat/ip_address.pp1
-rw-r--r--types/compat/ipv4.pp2
-rw-r--r--types/compat/ipv6.pp1
-rw-r--r--types/compat/numeric.pp23
-rw-r--r--types/compat/re.pp3
-rw-r--r--types/compat/string.pp2
-rw-r--r--types/httpsurl.pp1
-rw-r--r--types/httpurl.pp1
-rw-r--r--types/unixpath.pp2
-rw-r--r--types/windowspath.pp1
398 files changed, 11301 insertions, 5002 deletions
diff --git a/.fixtures.yml b/.fixtures.yml
index 37b7377..a28e653 100644
--- a/.fixtures.yml
+++ b/.fixtures.yml
@@ -1,3 +1,4 @@
fixtures:
symlinks:
stdlib: "#{source_dir}"
+ test: "#{source_dir}/spec/fixtures/test"
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..900ea0c
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,5 @@
+#This file is generated by ModuleSync, do not edit.
+*.rb eol=lf
+*.erb eol=lf
+*.pp eol=lf
+*.sh eol=lf
diff --git a/.gitignore b/.gitignore
index b5db85e..33bc5ff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,15 @@
+#This file is generated by ModuleSync, do not edit.
pkg/
Gemfile.lock
vendor/
-spec/fixtures/
+spec/fixtures/manifests/
+spec/fixtures/modules/
.vagrant/
.bundle/
coverage/
+log/
.idea/
*.iml
+!spec/fixtures/
+spec/fixtures/manifests/site.pp
+spec/fixtures/modules/*
diff --git a/.rspec b/.rspec
index 7ab5f55..16f9cdb 100644
--- a/.rspec
+++ b/.rspec
@@ -1,4 +1,2 @@
--color
---format
-progress
---backtrace
+--format documentation
diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000..5aadd1b
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,508 @@
+require: rubocop-rspec
+AllCops:
+ TargetRubyVersion: 1.9
+ Include:
+ - ./**/*.rb
+ Exclude:
+ - vendor/**/*
+ - .vendor/**/*
+ - pkg/**/*
+ - spec/fixtures/**/*
+Lint/ConditionPosition:
+ Enabled: True
+
+Lint/ElseLayout:
+ Enabled: True
+
+Lint/UnreachableCode:
+ Enabled: True
+
+Lint/UselessComparison:
+ Enabled: True
+
+Lint/EnsureReturn:
+ Enabled: True
+
+Lint/HandleExceptions:
+ Enabled: True
+
+Lint/LiteralInCondition:
+ Enabled: True
+
+Lint/ShadowingOuterLocalVariable:
+ Enabled: True
+
+Lint/LiteralInInterpolation:
+ Enabled: True
+
+Style/HashSyntax:
+ Enabled: True
+
+Style/RedundantReturn:
+ Enabled: True
+
+Lint/AmbiguousOperator:
+ Enabled: True
+
+Lint/AssignmentInCondition:
+ Enabled: True
+
+Style/SpaceBeforeComment:
+ Enabled: True
+
+Style/AndOr:
+ Enabled: True
+
+Style/RedundantSelf:
+ Enabled: True
+
+# Method length is not necessarily an indicator of code quality
+Metrics/MethodLength:
+ Enabled: False
+
+# Module length is not necessarily an indicator of code quality
+Metrics/ModuleLength:
+ Enabled: False
+
+Style/WhileUntilModifier:
+ Enabled: True
+
+Lint/AmbiguousRegexpLiteral:
+ Enabled: True
+
+Lint/Eval:
+ Enabled: True
+
+Lint/BlockAlignment:
+ Enabled: True
+
+Lint/DefEndAlignment:
+ Enabled: True
+
+Lint/EndAlignment:
+ Enabled: True
+
+Lint/DeprecatedClassMethods:
+ Enabled: True
+
+Lint/Loop:
+ Enabled: True
+
+Lint/ParenthesesAsGroupedExpression:
+ Enabled: True
+
+Lint/RescueException:
+ Enabled: True
+
+Lint/StringConversionInInterpolation:
+ Enabled: True
+
+Lint/UnusedBlockArgument:
+ Enabled: True
+
+Lint/UnusedMethodArgument:
+ Enabled: True
+
+Lint/UselessAccessModifier:
+ Enabled: True
+
+Lint/UselessAssignment:
+ Enabled: True
+
+Lint/Void:
+ Enabled: True
+
+Style/AccessModifierIndentation:
+ Enabled: True
+
+Style/AccessorMethodName:
+ Enabled: True
+
+Style/Alias:
+ Enabled: True
+
+Style/AlignArray:
+ Enabled: True
+
+Style/AlignHash:
+ Enabled: True
+
+Style/AlignParameters:
+ Enabled: True
+
+Metrics/BlockNesting:
+ Enabled: True
+
+Style/AsciiComments:
+ Enabled: True
+
+Style/Attr:
+ Enabled: True
+
+Style/BracesAroundHashParameters:
+ Enabled: True
+
+Style/CaseEquality:
+ Enabled: True
+
+Style/CaseIndentation:
+ Enabled: True
+
+Style/CharacterLiteral:
+ Enabled: True
+
+Style/ClassAndModuleCamelCase:
+ Enabled: True
+
+Style/ClassAndModuleChildren:
+ Enabled: False
+
+Style/ClassCheck:
+ Enabled: True
+
+# Class length is not necessarily an indicator of code quality
+Metrics/ClassLength:
+ Enabled: False
+
+Style/ClassMethods:
+ Enabled: True
+
+Style/ClassVars:
+ Enabled: True
+
+Style/WhenThen:
+ Enabled: True
+
+Style/WordArray:
+ Enabled: True
+
+Style/UnneededPercentQ:
+ Enabled: True
+
+Style/Tab:
+ Enabled: True
+
+Style/SpaceBeforeSemicolon:
+ Enabled: True
+
+Style/TrailingBlankLines:
+ Enabled: True
+
+Style/SpaceInsideBlockBraces:
+ Enabled: True
+
+Style/SpaceInsideBrackets:
+ Enabled: True
+
+Style/SpaceInsideHashLiteralBraces:
+ Enabled: True
+
+Style/SpaceInsideParens:
+ Enabled: True
+
+Style/LeadingCommentSpace:
+ Enabled: True
+
+Style/SpaceBeforeFirstArg:
+ Enabled: True
+
+Style/SpaceAfterColon:
+ Enabled: True
+
+Style/SpaceAfterComma:
+ Enabled: True
+
+Style/SpaceAfterMethodName:
+ Enabled: True
+
+Style/SpaceAfterNot:
+ Enabled: True
+
+Style/SpaceAfterSemicolon:
+ Enabled: True
+
+Style/SpaceAroundEqualsInParameterDefault:
+ Enabled: True
+
+Style/SpaceAroundOperators:
+ Enabled: True
+
+Style/SpaceBeforeBlockBraces:
+ Enabled: True
+
+Style/SpaceBeforeComma:
+ Enabled: True
+
+Style/CollectionMethods:
+ Enabled: True
+
+Style/CommentIndentation:
+ Enabled: True
+
+Style/ColonMethodCall:
+ Enabled: True
+
+Style/CommentAnnotation:
+ Enabled: True
+
+# 'Complexity' is very relative
+Metrics/CyclomaticComplexity:
+ Enabled: False
+
+Style/ConstantName:
+ Enabled: True
+
+Style/Documentation:
+ Enabled: False
+
+Style/DefWithParentheses:
+ Enabled: True
+
+Style/PreferredHashMethods:
+ Enabled: True
+
+Style/DotPosition:
+ EnforcedStyle: trailing
+
+Style/DoubleNegation:
+ Enabled: True
+
+Style/EachWithObject:
+ Enabled: True
+
+Style/EmptyLineBetweenDefs:
+ Enabled: True
+
+Style/IndentArray:
+ Enabled: True
+
+Style/IndentHash:
+ Enabled: True
+
+Style/IndentationConsistency:
+ Enabled: True
+
+Style/IndentationWidth:
+ Enabled: True
+
+Style/EmptyLines:
+ Enabled: True
+
+Style/EmptyLinesAroundAccessModifier:
+ Enabled: True
+
+Style/EmptyLiteral:
+ Enabled: True
+
+# Configuration parameters: AllowURI, URISchemes.
+Metrics/LineLength:
+ Enabled: False
+
+Style/MethodCallParentheses:
+ Enabled: True
+
+Style/MethodDefParentheses:
+ Enabled: True
+
+Style/LineEndConcatenation:
+ Enabled: True
+
+Style/TrailingWhitespace:
+ Enabled: True
+
+Style/StringLiterals:
+ Enabled: True
+
+Style/TrailingCommaInArguments:
+ Enabled: True
+
+Style/TrailingCommaInLiteral:
+ Enabled: True
+
+Style/GlobalVars:
+ Enabled: True
+
+Style/GuardClause:
+ Enabled: True
+
+Style/IfUnlessModifier:
+ Enabled: True
+
+Style/MultilineIfThen:
+ Enabled: True
+
+Style/NegatedIf:
+ Enabled: True
+
+Style/NegatedWhile:
+ Enabled: True
+
+Style/Next:
+ Enabled: True
+
+Style/SingleLineBlockParams:
+ Enabled: True
+
+Style/SingleLineMethods:
+ Enabled: True
+
+Style/SpecialGlobalVars:
+ Enabled: True
+
+Style/TrivialAccessors:
+ Enabled: True
+
+Style/UnlessElse:
+ Enabled: True
+
+Style/VariableInterpolation:
+ Enabled: True
+
+Style/VariableName:
+ Enabled: True
+
+Style/WhileUntilDo:
+ Enabled: True
+
+Style/EvenOdd:
+ Enabled: True
+
+Style/FileName:
+ Enabled: True
+
+Style/For:
+ Enabled: True
+
+Style/Lambda:
+ Enabled: True
+
+Style/MethodName:
+ Enabled: True
+
+Style/MultilineTernaryOperator:
+ Enabled: True
+
+Style/NestedTernaryOperator:
+ Enabled: True
+
+Style/NilComparison:
+ Enabled: True
+
+Style/FormatString:
+ Enabled: True
+
+Style/MultilineBlockChain:
+ Enabled: True
+
+Style/Semicolon:
+ Enabled: True
+
+Style/SignalException:
+ Enabled: True
+
+Style/NonNilCheck:
+ Enabled: True
+
+Style/Not:
+ Enabled: True
+
+Style/NumericLiterals:
+ Enabled: True
+
+Style/OneLineConditional:
+ Enabled: True
+
+Style/OpMethod:
+ Enabled: True
+
+Style/ParenthesesAroundCondition:
+ Enabled: True
+
+Style/PercentLiteralDelimiters:
+ Enabled: True
+
+Style/PerlBackrefs:
+ Enabled: True
+
+Style/PredicateName:
+ Enabled: True
+
+Style/RedundantException:
+ Enabled: True
+
+Style/SelfAssignment:
+ Enabled: True
+
+Style/Proc:
+ Enabled: True
+
+Style/RaiseArgs:
+ Enabled: True
+
+Style/RedundantBegin:
+ Enabled: True
+
+Style/RescueModifier:
+ Enabled: True
+
+# based on https://github.com/voxpupuli/modulesync_config/issues/168
+Style/RegexpLiteral:
+ EnforcedStyle: percent_r
+ Enabled: True
+
+Lint/UnderscorePrefixedVariableName:
+ Enabled: True
+
+Metrics/ParameterLists:
+ Enabled: False
+
+Lint/RequireParentheses:
+ Enabled: True
+
+Style/SpaceBeforeFirstArg:
+ Enabled: True
+
+Style/ModuleFunction:
+ Enabled: True
+
+Lint/Debugger:
+ Enabled: True
+
+Style/IfWithSemicolon:
+ Enabled: True
+
+Style/Encoding:
+ Enabled: True
+
+Style/BlockDelimiters:
+ Enabled: True
+
+Style/MultilineBlockLayout:
+ Enabled: True
+
+# 'Complexity' is very relative
+Metrics/AbcSize:
+ Enabled: False
+
+# 'Complexity' is very relative
+Metrics/PerceivedComplexity:
+ Enabled: False
+
+Lint/UselessAssignment:
+ Enabled: True
+
+Style/ClosingParenthesisIndentation:
+ Enabled: False
+
+# RSpec
+
+# We don't use rspec in this way
+RSpec/DescribeClass:
+ Enabled: False
+
+# Example length is not necessarily an indicator of code quality
+RSpec/ExampleLength:
+ Enabled: False
+
+RSpec/NamedSubject:
+ Enabled: False
diff --git a/.sync.yml b/.sync.yml
index 21e872e..34cfb5f 100644
--- a/.sync.yml
+++ b/.sync.yml
@@ -1,9 +1,18 @@
---
-.travis.yml:
- script: "\"bundle exec rake validate && bundle exec rake lint && bundle exec rake spec SPEC_OPTS='--color --format documentation'\""
-Rakefile:
- unmanaged: true
-Gemfile:
- unmanaged: true
+.gitignore:
+ paths:
+ - '!spec/fixtures/'
+ - 'spec/fixtures/manifests/site.pp'
+ - 'spec/fixtures/modules/*'
+
spec/spec_helper.rb:
- unmanaged: true
+ allow_deprecations: true
+
+.travis.yml:
+ extras:
+   - rvm: 2.1.9
+     env: PUPPET_GEM_VERSION="~> 4.6.0"
+     bundler_args: --without system_tests
+   - rvm: 2.1.9
+     env: PUPPET_GEM_VERSION="~> 4.7.0"
+     bundler_args: --without system_tests
diff --git a/.travis.yml b/.travis.yml
index 503e184..d972387 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,18 +1,41 @@
+#This file is generated by ModuleSync, do not edit.
---
sudo: false
language: ruby
-bundler_args: --without system_tests
-script: "bundle exec rake validate && bundle exec rake lint && bundle exec rake spec SPEC_OPTS='--color --format documentation'"
+cache: bundler
+script: "bundle exec rake validate lint spec"
+#Inserting below due to the following issue: https://github.com/travis-ci/travis-ci/issues/3531#issuecomment-88311203
+before_install:
+ - gem update bundler
matrix:
fast_finish: true
include:
- - rvm: 1.8.7
- env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.6.0"
- - rvm: 1.8.7
- env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.7.0"
- - rvm: 1.9.3
+ - rvm: 2.3.1
+ dist: trusty
+ env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_set=docker/ubuntu-14.04
+ script: bundle exec rake beaker
+ services: docker
+ sudo: required
+ - rvm: 2.3.1
+ dist: trusty
+ env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_set=docker/centos-7
+ script: bundle exec rake beaker
+ services: docker
+ sudo: required
+ - rvm: 2.3.1
+ bundler_args: --without system_tests
+ env: PUPPET_GEM_VERSION="~> 4.0"
+ - rvm: 2.1.9
+ bundler_args: --without system_tests
+ env: PUPPET_GEM_VERSION="~> 4.0"
+ - rvm: 2.1.5
+ bundler_args: --without system_tests
+ env: PUPPET_GEM_VERSION="~> 3.0" FUTURE_PARSER="yes"
+ - rvm: 2.1.5
+ bundler_args: --without system_tests
env: PUPPET_GEM_VERSION="~> 3.0"
- - rvm: 2.0.0
+ - rvm: 1.9.3
+ bundler_args: --without system_tests
env: PUPPET_GEM_VERSION="~> 3.0"
notifications:
email: false
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1385695..9157b2d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,17 +1,234 @@
-##2015-01-14 - Supported Release 4.6.0
+## Supported Release 4.13.1
+### Summary
+
+This bugfix release addresses the `undefined method 'optional_repeated_param'` error messages seen by users of puppet 3.7.
+
+It also improves the user experience around function deprecations by emitting one warning per function(-name) instead of only one deprecation overall. This allows users to identify all deprecated functions used in one agent run, with less back-and-forth.
+
+#### Bugfixes
+
+* Emit deprecations warnings for each function, instead of once per process. (MODULES-3961)
+* Use a universally available API for the v4 deprecation stubs of `is_*` and `validate_*`. (MODULES-3962)
+* Make `getvar()` compatible to ruby 1.8.7. (MODULES-3969)
+* Add v4 deprecation stubs for the `is_` counterparts of the deprecated functions to emit the deprecations warnings in all cases.
+
+
+## Supported Release 4.13.0
+### Summary
+
+This version of stdlib deprecates a whole host of functions, and provides stepping stones to move to Puppet 4 type validations. Be sure to check out the new `deprecation()` and `validate_legacy()` functions to migrate off the deprecated v3-style data validations.
+
+Many thanks to all community contributors: bob, Dmitry Ilyin, Dominic Cleal, Joris, Joseph Yaworski, Loic Antoine-Gombeaud, Maksym Melnychok, Michiel Brandenburg, Nate Potter, Romain Tartière, Stephen Benjamin, and Steve Moore, as well as anyone contributing in the code review process and by submitting issues.
+
+Special thanks to [Voxpupuli's](https://voxpupuli.org/) Igor Galić for donating the puppet-tea types to kickstart this part of stdlib.
+
+
+#### Deprecations
+* `validate_absolute_path`, `validate_array`, `validate_bool`, `validate_hash`, `validate_integer`, `validate_ip_address`, `validate_ipv4_address`, `validate_ipv6_address`, `validate_numeric`, `validate_re`, `validate_slength`, `validate_string`, and their `is_` counter parts are now deprecated on Puppet 4. See the `validate_legacy()` description in the README for help on migrating away from those functions.
+* The `dig` function is provided by core puppet since 4.5.0 with slightly different calling convention. The stdlib version can still be accessed as `dig44` for now.
+
+
+#### Features
+* Add Puppet 4 data types for Unix, and Windows paths, and URLs.
+* Add `deprecation` function to warn users of functionality that will be removed soon.
+* Add `validate_legacy` function to help with migrating to Puppet 4 data types.
+
+* Add `any2bool` function, a combination of of `string2bool` and `num2bool`.
+* Add `delete_regex` function to delete array elements matching a regular expression.
+* Add `puppet_environmentpath` fact to expose the `environmentpath` setting.
+* Add `regexpescape` function to safely insert arbitrary strings into regular expressions.
+* Add `shell_escape`, `shell_join`, and `shell_split` functions for safer working with shell scripts..
+
+* The `delete` function now also accepts regular expressions as search term.
+* The `loadyaml` function now accepts a default value, which is returned when there is an error loading the file.
+
+#### Bugfixes
+* Fix `file_line.match_for_absence` implementation and description to actually work. (MODULES-3590)
+* Fix `getparam` so that it can now also return `false`. (MODULES-3933)
+* Fix the fixture setup for testing and adjust `load_module_metadata` and `loadjson` tests.
+* Fix `defined_with_params` to handle `undef` correctly on all puppet versions. (PUP-6422, MODULES-3543)
+* Fix `file_line.path` validation to use puppet's built in `absolute_path?` matcher.
+
+#### Minor Improvements
+* README changes: improved descriptions of `deep_merge`, `delete`, `ensure_packages`, `file_line.after`, `range`, and `validate_numeric`.
+* The `getvar` function now returns nil in all situations where the variable is not found.
+* Update the `dig44` function with better `undef`, `nil`, and `false` handling.
+* Better wording on `str2bool` argument validation error message.
+
+
+### Known issues
+* The `validate_legacy` function relies on internal APIs from Puppet 4.4.0 (PE 2016.1) onwards, and doesn't work on earlier versions.
+* Puppet 4.5.0 (PE 2016.2) has a number of improvements around data types - especially error handling - that make working with them much nicer.
+
+## Supported Release 4.12.0
+###Summary
+
+This release provides several new functions, bugfixes, modulesync changes, and some documentation updates.
+
+####Features
+- Adds `clamp`. This function keeps values within a specified range.
+- Adds `validate_x509_rsa_key_pair`. This function validates an x509 RSA certificate and key pair.
+- Adds `dig`. This function performs a deep lookup in nested hashes or arrays.
+- Extends the `base64` support to fit `rfc2045` and `rfc4648`.
+- Adds `is_ipv6_address` and `is_ipv4_address`. These functions validate the specified ipv4 or ipv6 addresses.
+- Adds `enclose_ipv6`. This function encloses IPv6 addresses in square brackets.
+- Adds `ensure_resources`. This function takes a list of resources and creates them if they do not exist.
+- Extends `suffix` to support applying a suffix to keys in a hash.
+- Apply modulesync changes.
+- Add validate_email_address function.
+
+####Bugfixes
+- Fixes `fqdn_rand_string` tests, since Puppet 4.4.0 and later have a higher `fqdn_rand` ceiling.
+- (MODULES-3152) Adds a check to `package_provider` to prevent failures if Gem is not installed.
+- Fixes to README.md.
+- Fixes catch StandardError rather than the gratuitous Exception
+- Fixes file_line attribute validation.
+- Fixes concat with Hash arguments.
+
+## Supported Release 4.11.0
+###Summary
+
+Provides a validate_absolute_paths and Debian 8 support. There is a fix to the is_package_provider fact and a test improvement.
+
+####Features
+- Adds new parser called is_absolute_path
+- Supports Debian 8
+
+####Bugfixes
+- Allow package_provider fact to resolve on PE 3.x
+
+####Improvements
+- ensures that the test passes independently of changes to rubygems for ensure_resource
+
+##2015-12-15 - Supported Release 4.10.0
+###Summary
+
+Includes the addition of several new functions and considerable improvements to the existing functions, tests and documentation. Includes some bug fixes which includes compatibility, test and fact issues.
+
+####Features
+- Adds service_provider fact
+- Adds is_a() function
+- Adds package_provider fact
+- Adds validate_ip_address function
+- Adds seeded_rand function
+
+####Bugfixes
+- Fix backwards compatibility from an improvement to the parseyaml function
+- Renaming of load_module_metadata test to include _spec.rb
+- Fix root_home fact on AIX 5.x, now '-c' rather than '-C'
+- Fixed Gemfile to work with ruby 1.8.7
+
+####Improvements
+- (MODULES-2462) Improvement of parseyaml function
+- Improvement of str2bool function
+- Improvement to readme
+- Improvement of intersection function
+- Improvement of validate_re function
+- Improved speed on Facter resolution of service_provider
+- empty function now handles numeric values
+- Package_provider now prevents deprecation warning about the allow_virtual parameter
+- load_module_metadata now succeeds on empty file
+- Check added to ensure puppetversion value is not nil
+- Improvement to bool2str to return a string of choice using boolean
+- Improvement to naming convention in validate_ipv4_address function
+
+## Supported Release 4.9.1
+###Summary
+
+Small release for support of newer PE versions. This increments the version of PE in the metadata.json file.
+
+##2015-09-08 - Supported Release 4.9.0
+###Summary
+
+This release adds new features including the new functions dos2unix, unix2dos, try_get_value, convert_base as well as other features and improvements.
+
+####Features
+- (MODULES-2370) allow `match` parameter to influence `ensure => absent` behavior
+- (MODULES-2410) Add new functions dos2unix and unix2dos
+- (MODULE-2456) Modify union to accept more than two arrays
+- Adds a convert_base function, which can convert numbers between bases
+- Add a new function "try_get_value"
+
+####Bugfixes
+- n/a
+
+####Improvements
+- (MODULES-2478) Support root_home fact on AIX through "lsuser" command
+- Acceptance test improvements
+- Unit test improvements
+- Readme improvements
+
+## 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
-Improved functionality and preparing for Puppet Next with new parser
+Adds functions and function argument abilities, and improves compatibility with the new puppet parser
####Features
-- MODULES-444: concat can now take more than two arrays
-- basename function added to have Ruby File.basename functionality
-- delete function can now take an array of items to remove
-- MODULES-1473: deprecate type function in favor of type_of
+- MODULES-444: `concat()` can now take more than two arrays
+- `basename()` added to have Ruby File.basename functionality
+- `delete()` can now take an array of items to remove
+- `prefix()` can now take a hash
+- `upcase()` can now take a hash or array of upcaseable things
+- `validate_absolute_path()` can now take an array
+- `validate_cmd()` can now use % in the command to embed the validation file argument in the string
+- MODULES-1473: deprecate `type()` function in favor of `type3x()`
+- MODULES-1473: Add `type_of()` to give better type information on future parser
+- Deprecate `private()` for `assert_private()` due to future parser
+- Adds `ceiling()` to take the ceiling of a number
+- Adds `fqdn_rand_string()` to generate random string based on fqdn
+- Adds `pw_hash()` to generate password hashes
+- Adds `validate_integer()`
+- Adds `validate_numeric()` (like `validate_integer()` but also accepts floats)
####Bugfixes
-- Several test case fixes
-- Ensure_resource is more verbose on debug mode
+- Fix seeding of `fqdn_rotate()`
+- `ensure_resource()` is more verbose on debug mode
+- Stricter argument checking for `dirname()`
+- Fix `is_domain_name()` to better match RFC
+- Fix `uriescape()` when called with array
+- Fix `file_line` resource when using the `after` attribute with `match`
##2015-01-14 - Supported Release 4.5.1
###Summary
@@ -75,7 +292,7 @@ backwards-compatible with the stdlib 3 series. It adds two new functions, one bu
#### Features
- New `bool2str()` function
-- New `camalcase()` function
+- New `camelcase()` function
#### Bugfixes
- Fix `has_interface_with()` when interfaces fact is nil
@@ -278,7 +495,7 @@ This is a supported release
* Add an ensure\_packages function. (8a8c09e)
-##### 2012-11-23 - Erik Dalén <dalen@spotify.com> - 3.2.0
+##### 2012-11-23 - Erik Dalén <dalen@spotify.com> - 3.2.0
* (#17797) min() and max() functions (9954133)
@@ -375,7 +592,7 @@ This is a supported release
* Add support for a 'match' parameter to file\_line (a06c0d8)
-##### 2012-08-07 - Erik Dalén <dalen@spotify.com> - 2.4.0
+##### 2012-08-07 - Erik Dalén <dalen@spotify.com> - 2.4.0
* (#15872) Add to\_bytes function (247b69c)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f1cbde4..3c3f1e7 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -159,7 +159,7 @@ If you already have those gems installed, make sure they are up-to-date:
With all dependencies in place and up-to-date we can now run the tests:
```shell
-% rake spec
+% bundle exec rake spec
```
This will execute all the [rspec tests](http://rspec-puppet.com/) tests
@@ -178,8 +178,8 @@ installed on your system.
You can run them by issuing the following command
```shell
-% rake spec_clean
-% rspec spec/acceptance
+% bundle exec rake spec_clean
+% bundle exec rspec spec/acceptance
```
This will now download a pre-fabricated image configured in the [default node-set](./spec/acceptance/nodesets/default.yml),
@@ -208,11 +208,9 @@ review.
Additional Resources
====================
-* [Getting additional help](http://puppetlabs.com/community/get-help)
+* [Getting additional help](http://puppet.com/community/get-help)
-* [Writing tests](http://projects.puppetlabs.com/projects/puppet/wiki/Development_Writing_Tests)
-
-* [Patchwork](https://patchwork.puppetlabs.com)
+* [Writing tests](https://docs.puppet.com/guides/module_guides/bgtm.html#step-three-module-testing)
* [General GitHub documentation](http://help.github.com/)
diff --git a/Gemfile b/Gemfile
index 74a16f3..3d46720 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,35 +1,87 @@
-source ENV['GEM_SOURCE'] || 'https://rubygems.org'
+#This file is generated by ModuleSync, do not edit.
-def location_for(place, fake_version = nil)
- if place =~ /^(git[:@][^#]*)#(.*)/
+source ENV['GEM_SOURCE'] || "https://rubygems.org"
+
+# Determines what type of gem is requested based on place_or_version.
+def gem_type(place_or_version)
+ if place_or_version =~ /^git:/
+ :git
+ elsif place_or_version =~ /^file:/
+ :file
+ else
+ :gem
+ end
+end
+
+# Find a location or specific version for a gem. place_or_version can be a
+# version, which is most often used. It can also be git, which is specified as
+# `git://somewhere.git#branch`. You can also use a file source location, which
+# is specified as `file://some/location/on/disk`.
+def location_for(place_or_version, fake_version = nil)
+ if place_or_version =~ /^(git[:@][^#]*)#(.*)/
[fake_version, { :git => $1, :branch => $2, :require => false }].compact
- elsif place =~ /^file:\/\/(.*)/
+ elsif place_or_version =~ /^file:\/\/(.*)/
['>= 0', { :path => File.expand_path($1), :require => false }]
else
- [place, { :require => false }]
+ [place_or_version, { :require => false }]
end
end
-group :development, :unit_tests do
- gem 'rake', '~> 10.1.0', :require => false
- gem 'rspec-puppet', :require => false
- gem 'puppetlabs_spec_helper', :require => false
- gem 'puppet-lint', :require => false
- gem 'pry', :require => false
- gem 'simplecov', :require => false
+# Used for gem conditionals
+supports_windows = false
+
+group :development do
+ gem 'puppet-lint', :require => false
+ gem 'metadata-json-lint', :require => false, :platforms => 'ruby'
+ gem 'puppet_facts', :require => false
+ gem 'puppet-blacksmith', '>= 3.4.0', :require => false, :platforms => 'ruby'
+ gem 'puppetlabs_spec_helper', '>= 1.2.1', :require => false
+ gem 'rspec-puppet', '>= 2.3.2', :require => false
+ gem 'rspec-puppet-facts', :require => false, :platforms => 'ruby'
+ gem 'mocha', '< 1.2.0', :require => false
+ gem 'simplecov', :require => false, :platforms => 'ruby'
+ gem 'parallel_tests', '< 2.10.0', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0')
+ gem 'parallel_tests', :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.0.0')
+ gem 'rubocop', '0.41.2', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0')
+ gem 'rubocop', :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.0.0')
+ gem 'rubocop-rspec', '~> 1.6', :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0')
+ gem 'pry', :require => false
+ gem 'json_pure', '<= 2.0.1', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0')
+ gem 'fast_gettext', '1.1.0', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0')
+ gem 'fast_gettext', :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0')
end
group :system_tests do
- gem 'beaker-rspec', :require => false
- gem 'serverspec', :require => false
+ gem 'beaker', *location_for(ENV['BEAKER_VERSION'] || '~> 2.20') if supports_windows
+ gem 'beaker', *location_for(ENV['BEAKER_VERSION']) if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0') and ! supports_windows
+ gem 'beaker', *location_for(ENV['BEAKER_VERSION'] || '< 3') if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.3.0') and ! supports_windows
+ gem 'beaker-pe', :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0')
+ gem 'beaker-rspec', *location_for(ENV['BEAKER_RSPEC_VERSION'] || '>= 3.4') if ! supports_windows
+ gem 'beaker-rspec', *location_for(ENV['BEAKER_RSPEC_VERSION'] || '~> 5.1') if supports_windows
+ gem 'beaker-puppet_install_helper', :require => false
+ gem 'master_manipulator', :require => false
+ gem 'beaker-hostgenerator', *location_for(ENV['BEAKER_HOSTGENERATOR_VERSION'])
+ gem 'beaker-abs', *location_for(ENV['BEAKER_ABS_VERSION'] || '~> 0.1')
+end
+
+gem 'puppet', *location_for(ENV['PUPPET_GEM_VERSION'])
+
+# Only explicitly specify Facter/Hiera if a version has been specified.
+# Otherwise it can lead to strange bundler behavior. If you are seeing weird
+# gem resolution behavior, try setting `DEBUG_RESOLVER` environment variable
+# to `1` and then run bundle install.
+gem 'facter', *location_for(ENV['FACTER_GEM_VERSION']) if ENV['FACTER_GEM_VERSION']
+gem 'hiera', *location_for(ENV['HIERA_GEM_VERSION']) if ENV['HIERA_GEM_VERSION']
+
+
+# Evaluate Gemfile.local if it exists
+if File.exists? "#{__FILE__}.local"
+ eval(File.read("#{__FILE__}.local"), binding)
end
-ENV['GEM_PUPPET_VERSION'] ||= ENV['PUPPET_GEM_VERSION']
-puppetversion = ENV['GEM_PUPPET_VERSION']
-if puppetversion
- gem 'puppet', *location_for(puppetversion)
-else
- gem 'puppet', :require => false
+# Evaluate ~/.gemfile if it exists
+if File.exists?(File.join(Dir.home, '.gemfile'))
+ eval(File.read(File.join(Dir.home, '.gemfile')), binding)
end
# vim:ft=ruby
diff --git a/LICENSE b/LICENSE
index ec0587c..d645695 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,19 +1,202 @@
-Copyright (C) 2011 Puppet Labs Inc
-and some parts:
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
-Copyright (C) 2011 Krzysztof Wilczynski
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-Puppet Labs can be contacted at: info@puppetlabs.com
+ 1. Definitions.
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
- http://www.apache.org/licenses/LICENSE-2.0
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..3c8c03a
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,23 @@
+stdlib puppet module
+
+Copyright (C) 2011-2016 Puppet Labs, Inc.
+
+and some parts:
+
+Copyright (C) 2011 Krzysztof Wilczynski
+
+
+Puppet Labs can be contacted at: info@puppetlabs.com
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/README.markdown b/README.markdown
index e9a1f4e..a4c30b5 100644
--- a/README.markdown
+++ b/README.markdown
@@ -1,8 +1,6 @@
-#stdlib
+# stdlib
-[![Build Status](https://travis-ci.org/puppetlabs/puppetlabs-stdlib.png?branch=master)](https://travis-ci.org/puppetlabs/puppetlabs-stdlib)
-
-####Table of Contents
+#### Table of Contents
1. [Overview](#overview)
2. [Module Description - What the module does and why it is useful](#module-description)
@@ -12,51 +10,38 @@
5. [Limitations - OS compatibility, etc.](#limitations)
6. [Development - Guide for contributing to the module](#development)
-##Overview
+## Overview
Adds a standard library of resources for Puppet modules.
-##Module Description
+## Module Description
-This module provides a standard library of resources for the development of Puppet
-modules. Puppet modules make heavy use of this standard library. The stdlib module adds the following resources to Puppet:
+This module provides a standard library of resources for the development of Puppet modules. Puppet modules make heavy use of this standard library. The stdlib module adds the following resources to Puppet:
* Stages
* Facts
* Functions
* Defined resource types
- * Types
+ * Data Types
* Providers
> *Note:* As of version 3.7, Puppet Enterprise no longer includes the stdlib module. If you're running Puppet Enterprise, you should install the most recent release of stdlib for compatibility with Puppet modules.
-##Setup
+## Setup
Installing the stdlib module adds the functions, facts, and resources of this standard library to Puppet.
-##Usage
+## Usage
After you've installed stdlib, all of its functions, facts, and resources are available for module use or development.
If you want to use a standardized set of run stages for Puppet, `include stdlib` in your manifest.
-## Reference
-
-### Classes
-
-#### Public Classes
-
* `stdlib`: Most of stdlib's features are automatically loaded by Puppet. To use standardized run stages in Puppet, declare this class in your manifest with `include stdlib`.
When declared, stdlib declares all other classes in the module. The only other class currently included in the module is `stdlib::stages`.
- The stdlib class has no parameters.
-
-#### Private Classes
-
-* `stdlib::stages`: This class manages a standard set of run stages for Puppet. It is managed by the stdlib class and should not be declared independently.
-
- The `stdlib::stages` class declares various run stages for deploying infrastructure, language runtimes, and application layers. The high level stages are (in order):
+The `stdlib::stages` class declares various run stages for deploying infrastructure, language runtimes, and application layers. The high level stages are (in order):
* setup
* main
@@ -69,75 +54,258 @@ If you want to use a standardized set of run stages for Puppet, `include stdlib`
Sample usage:
- ```
+ ~~~
node default {
include stdlib
class { java: stage => 'runtime' }
}
- ```
+ ~~~
-### Resources
+## Reference
-* `file_line`: This resource ensures that a given line, including whitespace at the beginning and end, is contained within a file. If the line is not contained in the given file, Puppet will add the line. Multiple resources can be declared to manage multiple lines in the same file. You can also use match to replace existing lines.
+### Classes
- ```
- file_line { 'sudo_rule':
- path => '/etc/sudoers',
- line => '%sudo ALL=(ALL) ALL',
- }
- file_line { 'sudo_rule_nopw':
- path => '/etc/sudoers',
- line => '%sudonopw ALL=(ALL) NOPASSWD: ALL',
- }
- ```
+#### Public Classes
+
+ The stdlib class has no parameters.
+
+#### Private Classes
+
+* `stdlib::stages`: Manages a standard set of run stages for Puppet. It is managed by the stdlib class and should not be declared independently.
+
+### Resource Types
+
+#### `file_line`
+
+Ensures that a given line is contained within a file. The implementation matches the full line, including whitespace at the beginning and end. If the line is not contained in the given file, Puppet appends the line to the end of the file to ensure the desired state. Multiple resources can be declared to manage multiple lines in the same file.
+
+Example:
+
+ file_line { 'sudo_rule':
+ path => '/etc/sudoers',
+ line => '%sudo ALL=(ALL) ALL',
+ }
+
+ file_line { 'sudo_rule_nopw':
+ path => '/etc/sudoers',
+ line => '%sudonopw ALL=(ALL) NOPASSWD: ALL',
+ }
+
+In this example, Puppet ensures that both of the specified lines are contained in the file `/etc/sudoers`.
+
+Match Example:
+
+ file_line { 'bashrc_proxy':
+ ensure => present,
+ path => '/etc/bashrc',
+ line => 'export HTTP_PROXY=http://squid.puppetlabs.vm:3128',
+ match => '^export\ HTTP_PROXY\=',
+ }
+
+In this code example, `match` looks for a line beginning with export followed by HTTP_PROXY and replaces 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` looks 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 contains the line being managed, the `file_line` resource autorequires that file.
+
+##### Parameters
+
+All parameters are optional, unless otherwise noted.
+
+* `after`: Specifies the line after which Puppet adds any new lines using a regular expression. (Existing lines are added in place.) Valid options: String containing a regex. Default: Undefined.
+* `ensure`: Ensures whether the resource is present. Valid options: 'present', 'absent'. Default: 'present'.
+* `line`: **Required.** Sets the line to be added to the file located by the `path` parameter. Valid options: String. Default: Undefined.
+* `match`: Specifies a regular expression to run against existing lines in the file; if a match is found, it is replaced rather than adding a new line. A regex comparison is performed against the line value, and if it does not match, an exception is raised. Valid options: String containing a regex. Default: Undefined.
+* `match_for_absence`: 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` and the value of `line` is used instead. Ignored when `ensure => present`. Default: false.
+* `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
+
+### Data Types
+
+#### `Stdlib::Absolutepath`
+
+A strict absolute path type. Uses a Variant of Unixpath and Windowspath types.
+
+Acceptable input examples: /var/log
+ /usr2/username/bin:/usr/local/bin:/usr/bin:.
+ C:\\WINDOWS\\System32
+Unacceptable input example: ../relative_path
+
+#### `Stdlib::Httpsurl`
+
+Matches https URLs.
+
+Acceptable input example: https://hello.com
+Unacceptable input example: httds://notquiteright.org
+
+#### `Stdlib::Httpurl`
+
+Matches both https and http URLs.
+
+Acceptable input example: https://hello.com
+ http://hello.com
+Unacceptable input example: httds://notquiteright.org
+
+#### `Stdlib::Unixpath`
+
+Matches paths on Unix type Operating Systems.
+
+Acceptable input example: /usr2/username/bin:/usr/local/bin:/usr/bin:.
+ /var/tmp
+Unacceptable input example: C:/whatever
+
+#### `Stdlib::Windowspath`
- * `after`: Specify the line after which Puppet will add any new lines. (Existing lines are added in place.) Optional.
- * `ensure`: Ensures whether the resource is present. Valid values are 'present', 'absent'.
- * `line`: The line to be added to the file located by the `path` parameter.
- * `match`: A regular expression to run against existing lines in the file; if a match is found, we replace that line rather than adding a new line. Optional.
- * `multiple`: Determine if match can change multiple lines. Valid values are 'true', 'false'. Optional.
- * `name`: An arbitrary name used as the identity of the resource.
- * `path`: The file in which Puppet will ensure the line specified by the line parameter.
+Matches paths on Windows Operating systems.
+
+Acceptable input example: C:\\WINDOWS\\System32
+ C:\\
+ \\\\host\\windows
+Unacceptable input example: /usr2/username/bin:/usr/local/bin:/usr/bin:.
### Functions
-* `abs`: Returns the absolute value of a number; for example, '-34.56' becomes '34.56'. Takes a single integer and float value as an argument. *Type*: rvalue
+#### `abs`
+
+Returns the absolute value of a number; for example, '-34.56' becomes '34.56'. Takes a single integer and float value as an argument. *Type*: rvalue.
+
+#### `any2array`
+
+Converts any object to an array containing that object. Empty argument lists are converted to an empty array. Arrays are left untouched. Hashes are converted to arrays of alternating keys and values. *Type*: rvalue.
+
+#### `base64`
+
+Converts a string to and from base64 encoding. Requires an `action` ('encode', 'decode') and either a plain or base64-encoded `string`, and an optional `method` ('default', 'strict', 'urlsafe')
+
+For backward compatibility, `method` will be set as `default` if not specified.
-* `any2array`: This converts any object to an array containing that object. Empty argument lists are converted to an empty array. Arrays are left untouched. Hashes are converted to arrays of alternating keys and values. *Type*: rvalue
+*Examples:*
+~~~
+base64('encode', 'hello')
+base64('encode', 'hello', 'default')
+# return: "aGVsbG8=\n"
-* `base64`: Converts a string to and from base64 encoding.
-Requires an action ('encode', 'decode') and either a plain or base64-encoded
-string. *Type*: rvalue
+base64('encode', 'hello', 'strict')
+# return: "aGVsbG8="
-* `basename`: Returns the `basename` of a path (optionally stripping an extension). For example:
+base64('decode', 'aGVsbG8=')
+base64('decode', 'aGVsbG8=\n')
+base64('decode', 'aGVsbG8=', 'default')
+base64('decode', 'aGVsbG8=\n', 'default')
+base64('decode', 'aGVsbG8=', 'strict')
+# return: "hello"
+
+base64('encode', 'https://puppetlabs.com', 'urlsafe')
+# return: "aHR0cHM6Ly9wdXBwZXRsYWJzLmNvbQ=="
+
+base64('decode', 'aHR0cHM6Ly9wdXBwZXRsYWJzLmNvbQ==', 'urlsafe')
+# return: "https://puppetlabs.com"
+~~~
+
+*Type*: rvalue.
+
+#### `basename`
+
+Returns the `basename` of a path (optionally stripping an extension). For example:
* ('/path/to/a/file.ext') returns 'file.ext'
* ('relative/path/file.ext') returns 'file.ext'
* ('/path/to/a/file.ext', '.ext') returns 'file'
- *Type*: rvalue
+*Type*: rvalue.
+
+#### `bool2num`
-* `bool2num`: Converts a boolean to a number. Converts values:
+Converts a boolean to a number. Converts values:
* 'false', 'f', '0', 'n', and 'no' to 0.
* 'true', 't', '1', 'y', and 'yes' to 1.
- Requires a single boolean or string as an input. *Type*: rvalue
+ Requires a single boolean or string as an input. *Type*: rvalue.
+
+#### `bool2str`
+
+Converts a boolean to a string using optionally supplied arguments. The optional second and third arguments represent what true and false are converted to respectively. If only one argument is given, it is converted from a boolean to a string containing 'true' or 'false'.
+
+*Examples:*
+~~~
+bool2str(true) => 'true'
+bool2str(true, 'yes', 'no') => 'yes'
+bool2str(false, 't', 'f') => 'f'
+~~~
+
+Requires a single boolean as input. *Type*: rvalue.
+
+#### `capitalize`
+
+Capitalizes the first character of a string or array of strings and lowercases the remaining characters of each string. Requires either a single string or an array as an input. *Type*: rvalue.
+
+#### `ceiling`
+
+Returns the smallest integer greater than or equal to the argument. Takes a single numeric value as an argument. *Type*: rvalue.
+
+#### `chomp`
+
+Removes the record separator from the end of a string or an array of strings; for example, 'hello\n' becomes 'hello'. Requires a single string or array as an input. *Type*: rvalue.
+
+#### `chop`
+
+Returns a new string with the last character removed. If the string ends with '\r\n', both characters are removed. Applying `chop` to an empty string returns an empty string. If you want to merely remove record separators, then you should use the `chomp` function. Requires a string or an array of strings as input. *Type*: rvalue.
+
+#### `clamp`
+
+Keeps value within the range [Min, X, Max] by sort based on integer value (order of params doesn't matter). Takes strings, arrays or numerics. Strings are converted and compared numerically. Arrays of values are flattened into a list for further handling. For example:
+ * `clamp('24', [575, 187])` returns 187.
+ * `clamp(16, 88, 661)` returns 88.
+ * `clamp([4, 3, '99'])` returns 4.
+ *Type*: rvalue.
-* `capitalize`: Capitalizes the first letter of a string or array of strings.
-Requires either a single string or an array as an input. *Type*: rvalue
+#### `concat`
-* `chomp`: Removes the record separator from the end of a string or an array of
-strings; for example, 'hello\n' becomes 'hello'. Requires a single string or array as an input. *Type*: rvalue
+Appends the contents of multiple arrays onto the first array given. For example:
+ * `concat(['1','2','3'],'4')` returns ['1','2','3','4'].
+ * `concat(['1','2','3'],'4',['5','6','7'])` returns ['1','2','3','4','5','6','7'].
+ *Type*: rvalue.
-* `chop`: Returns a new string with the last character removed. If the string ends with '\r\n', both characters are removed. Applying `chop` to an empty string returns an empty string. If you want to merely remove record separators, then you should use the `chomp` function. Requires a string or an array of strings as input. *Type*: rvalue
+#### `convert_base`
-* `concat`: Appends the contents of multiple arrays onto array 1. For example:
- * `concat(['1','2','3'],'4')` results in: ['1','2','3','4'].
- * `concat(['1','2','3'],'4',['5','6','7'])` results in: ['1','2','3','4','5','6','7'].
+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`: Takes an array as first argument and an optional second argument. Count the number of elements in array that matches second argument. If called with only an array, it counts the number of elements that are **not** nil/undef. *Type*: rvalue
+#### `count`
-* `defined_with_params`: Takes a resource reference and an optional hash of attributes. Returns 'true' if a resource with the specified attributes has already been added to the catalog. Returns 'false' otherwise.
+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.
- ```
+#### `deep_merge`
+
+Recursively merges two or more hashes together and returns the resulting hash.
+ $hash1 = {'one' => 1, 'two' => 2, 'three' => { 'four' => 4 } }
+ $hash2 = {'two' => 'dos', 'three' => { 'five' => 5 } }
+ $merged_hash = deep_merge($hash1, $hash2)
+
+The resulting hash is equivalent to:
+ $merged_hash = { 'one' => 1, 'two' => 'dos', 'three' => { 'four' => 4, 'five' => 5 } }
+
+When there is a duplicate key that is a hash, they are recursively merged. When there is a duplicate key that is not a hash, the key in the rightmost hash will "win.".
+*Type*: rvalue, rvalue.
+
+#### `defined_with_params`
+
+Takes a resource reference and an optional hash of attributes. Returns 'true' if a resource with the specified attributes has already been added to the catalog. Returns 'false' otherwise.
+
+ ~~~
user { 'dan':
ensure => present,
}
@@ -145,70 +313,295 @@ strings; for example, 'hello\n' becomes 'hello'. Requires a single string or arr
if ! defined_with_params(User[dan], {'ensure' => 'present' }) {
user { 'dan': ensure => present, }
}
- ```
+ ~~~
- *Type*: rvalue
+*Type*: rvalue.
-* `delete`: Deletes all instances of a given element from an array, substring from a
-string, or key from a hash. For example, `delete(['a','b','c','b'], 'b')` returns ['a','c']; `delete('abracadabra', 'bra')` returns 'acada'. `delete({'a' => 1,'b' => 2,'c' => 3},['b','c'])` returns {'a'=> 1} *Type*: rvalue
+#### `delete`
-* `delete_at`: Deletes a determined indexed value from an array. For example, `delete_at(['a','b','c'], 1)` returns ['a','c']. *Type*: rvalue
+Deletes all instances of a given element from an array, substring from a string, or key from a hash.
-* `delete_values`: Deletes all instances of a given value from a hash. For example, `delete_values({'a'=>'A','b'=>'B','c'=>'C','B'=>'D'}, 'B')` returns {'a'=>'A','c'=>'C','B'=>'D'} *Type*: rvalue
+For example, `delete(['a','b','c','b'], 'b')` returns ['a','c']; `delete('abracadabra', 'bra')` returns 'acada'. `delete({'a' => 1,'b' => 2,'c' => 3},['b','c'])` returns {'a'=> 1}, `delete(['ab', 'b'], 'b')` returns ['ab'].
-* `delete_undef_values`: Deletes all instances of the undef value from an array or hash. For example, `$hash = delete_undef_values({a=>'A', b=>'', c=>undef, d => false})` returns {a => 'A', b => '', d => false}. *Type*: rvalue
+*Type*: rvalue.
-* `difference`: Returns the difference between two arrays.
-The returned array is a copy of the original array, removing any items that
-also appear in the second array. For example, `difference(["a","b","c"],["b","c","d"])` returns ["a"].
+#### `delete_at`
-* `dirname`: Returns the `dirname` of a path. For example, `dirname('/path/to/a/file.ext')` returns '/path/to/a'.
+Deletes a determined indexed value from an array. For example, `delete_at(['a','b','c'], 1)` returns ['a','c']. *Type*: rvalue.
-* `downcase`: Converts the case of a string or of all strings in an array to lowercase. *Type*: rvalue
+#### `delete_regex`
-* `empty`: Returns 'true' if the variable is empty. *Type*: rvalue
+Deletes all instances of a given element from an array or hash that match a provided regular expression. A string will be treated as a one-item array.
-* `ensure_packages`: Takes a list of packages and only installs them if they don't already exist. It optionally takes a hash as a second parameter to be passed as the third argument to the `ensure_resource()` function. *Type*: statement
+For example, `delete_regex(['a','b','c','b'], 'b')` returns ['a','c']; `delete_regex({'a' => 1,'b' => 2,'c' => 3},['b','c'])` returns {'a'=> 1}, `delete_regex(['abf', 'ab', 'ac'], '^ab.*')` returns ['ac']. `delete_regex(['ab', 'b'], 'b')` returns ['ab'].
-* `ensure_resource`: Takes a resource type, title, and a list of attributes that describe a resource.
+*Type*: rvalue.
- ```
- user { 'dan':
- ensure => present,
+#### `delete_values`
+
+Deletes all instances of a given value from a hash. For example, `delete_values({'a'=>'A','b'=>'B','c'=>'C','B'=>'D'}, 'B')` returns {'a'=>'A','c'=>'C','B'=>'D'} *Type*: rvalue.
+
+#### `delete_undef_values`
+
+Deletes all instances of the undef value from an array or hash. For example, `$hash = delete_undef_values({a=>'A', b=>'', c=>undef, d => false})` returns {a => 'A', b => '', d => false}. *Type*: rvalue.
+
+#### `deprecation`
+
+Prints deprecation warnings and logs a warning once for a given key:
+
+```
+deprecation(key, message)
+```
+
+* key: to keep the number of messages low, during the lifetime of a puppet process, only one message per key is logged.
+* message: the text to be logged.
+
+The Puppet settings '[disable_warnings](https://docs.puppet.com/puppet/latest/reference/configuration.html#disablewarnings)', '[max_deprecations](https://docs.puppet.com/puppet/latest/reference/configuration.html#maxdeprecations)', and '[strict](https://docs.puppet.com/puppet/latest/reference/configuration.html#strict)' affect this function. Set 'strict' to `error` to fail immediately with the deprecation message, `off` to output emit no messages at all, or `warning` (default) to log all warnings.
+
+Additionally you can set the environment variable `STDLIB_LOG_DEPRECATIONS` to decide whether or not to log deprecation warnings: if this environment variable is set to `true`, the functions log a warning, if it is set to `false`, no warnings are logged. If no value is set at all, Puppet 4 will emit warnings, while Puppet 3 will not. Using this setting is especially useful for automated tests to avoid flooding your logs before you are ready to migrate.
+
+*Type*: String, String.
+
+#### `difference`
+
+Returns the difference between two arrays. The returned array is a copy of the original array, removing any items that also appear in the second array. For example, `difference(["a","b","c"],["b","c","d"])` returns ["a"]. *Type*: rvalue.
+
+#### `dig`
+
+DEPRECATED: This function has been replaced in Puppet 4.5.0, use dig44() for backwards compatibility or use the new version.
+
+*Type*: rvalue.
+
+Retrieves a value within multiple layers of hashes and arrays via an array of keys containing a path. The function goes through the structure by each path component and tries to return the value at the end of the path.
+
+In addition to the required path argument, the function accepts the default argument. It is returned if the path is not correct, if no value was found, or if any other error has occurred.
+
+~~~ruby
+$data = {
+ 'a' => {
+ 'b' => [
+ 'b1',
+ 'b2',
+ 'b3',
+ ]
}
- ```
+}
- This example only creates the resource if it does not already exist:
+$value = dig($data, ['a', 'b', 2])
+# $value = 'b3'
- `ensure_resource('user', 'dan', {'ensure' => 'present' })`
+# with all possible options
+$value = dig($data, ['a', 'b', 2], 'not_found')
+# $value = 'b3'
- If the resource already exists, but does not match the specified parameters, this function attempts to recreate the resource, leading to a duplicate resource definition error.
+# using the default value
+$value = dig($data, ['a', 'b', 'c', 'd'], 'not_found')
+# $value = 'not_found'
+~~~
- An array of resources can also be passed in, and each will be created with the type and parameters specified if it doesn't already exist.
+1. **$data** The data structure we are working with.
+2. **['a', 'b', 2]** The path array.
+3. **'not_found'** The default value. It will be returned if nothing is found.
+ (optional, defaults to *undef*)
+
+#### `dig44`
+
+*Type*: rvalue.
+
+Retrieves a value within multiple layers of hashes and arrays via an array of keys containing a path. The function goes through the structure by each path component and tries to return the value at the end of the path.
+
+In addition to the required path argument, the function accepts the default argument. It is returned if the path is not correct, if no value was found, or if any other error has occurred.
+
+~~~ruby
+$data = {
+ 'a' => {
+ 'b' => [
+ 'b1',
+ 'b2',
+ 'b3',
+ ]
+ }
+}
+
+$value = dig44($data, ['a', 'b', 2])
+# $value = 'b3'
+
+# with all possible options
+$value = dig44($data, ['a', 'b', 2], 'not_found')
+# $value = 'b3'
+
+# using the default value
+$value = dig44($data, ['a', 'b', 'c', 'd'], 'not_found')
+# $value = 'not_found'
+~~~
+
+1. **$data** The data structure we are working with.
+2. **['a', 'b', 2]** The path array.
+3. **'not_found'** The default value. It will be returned if nothing is found.
+ (optional, defaults to *undef*)
+
+#### `dirname`
+
+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.
+
+#### `empty`
+
+Returns true if the argument is an array or hash that contains no elements, or an empty string. Returns false when the argument is a numerical value. *Type*: rvalue.
+
+#### `enclose_ipv6`
+
+Takes an array of ip addresses and encloses the ipv6 addresses with square brackets. *Type*: rvalue.
+
+#### `ensure_packages`
+
+Takes a list of packages array/hash and only installs them if they don't already exist. It optionally takes a hash as a second parameter to be passed as the third argument to the `ensure_resource()` or `ensure_resources()` function. *Type*: statement.
+
+For Array:
+
+ ensure_packages(['ksh','openssl'], {'ensure' => 'present'})
+
+For Hash:
+
+ ensure_packages({'ksh' => { ensure => '20120801-1' } , 'mypackage' => { source => '/tmp/myrpm-1.0.0.x86_64.rpm', provider => "rpm" }}, {'ensure' => 'present'})
+
+#### `ensure_resource`
+
+Takes a resource type, title, and a hash of attributes that describe the resource(s).
+
+~~~
+user { 'dan':
+ ensure => present,
+}
+~~~
+
+This example only creates the resource if it does not already exist:
+
+ `ensure_resource('user', 'dan', {'ensure' => 'present' })`
+
+If the resource already exists, but does not match the specified parameters, this function attempts to recreate the resource, leading to a duplicate resource definition error.
+
+An array of resources can also be passed in, and each will be created with the type and parameters specified if it doesn't already exist.
`ensure_resource('user', ['dan','alex'], {'ensure' => 'present'})`
- *Type*: statement
+*Type*: statement.
+
+#### `ensure_resources`
+
+Takes a resource type, title (only hash), and a hash of attributes that describe the resource(s).
+
+~~~
+user { 'dan':
+ gid => 'mygroup',
+ ensure => present,
+}
+
+ensure_resources($user)
+~~~
+
+An hash of resources should be passed in and each will be created with the type and parameters specified if it doesn't already exist:
+
+ ensure_resources('user', {'dan' => { gid => 'mygroup', uid => '600' } , 'alex' => { gid => 'mygroup' }}, {'ensure' => 'present'})
+
+From Hiera Backend:
+
+~~~
+userlist:
+ dan:
+ gid: 'mygroup'
+ uid: '600'
+ alex:
+ gid: 'mygroup'
+
+ensure_resources('user', hiera_hash('userlist'), {'ensure' => 'present'})
+~~~
+
+### `flatten`
+
+Flattens deeply nested arrays and returns a single flat array as a result. For example, `flatten(['a', ['b', ['c']]])` returns ['a','b','c']. *Type*: rvalue.
+
+#### `floor`
+
+Takes a single numeric value as an argument, and returns the largest integer less than or equal to the argument. *Type*: rvalue.
+
+#### `fqdn_rand_string`
+
+Generates a random alphanumeric string using an optionally-specified character set (default is alphanumeric), combining the `$fqdn` fact and an optional seed for repeatable randomness.
+
+*Usage:*
+~~~
+fqdn_rand_string(LENGTH, [CHARSET], [SEED])
+~~~
+*Examples:*
+~~~
+fqdn_rand_string(10)
+fqdn_rand_string(10, 'ABCDEF!@#$%^')
+fqdn_rand_string(10, '', 'custom seed')
+~~~
+
+*Type*: rvalue.
+
+#### `fqdn_rotate`
-* `flatten`: This function flattens any deeply nested arrays and returns a single flat array as a result. For example, `flatten(['a', ['b', ['c']]])` returns ['a','b','c']. *Type*: rvalue
+Rotates an array or string a random number of times, combining the `$fqdn` fact and an optional seed for repeatable randomness.
-* `floor`: Returns the largest integer less than or equal to the argument.
-Takes a single numeric value as an argument. *Type*: rvalue
+*Usage:*
-* `fqdn_rotate`: Rotates an array a random number of times based on a node's fqdn. *Type*: rvalue
+~~~
+fqdn_rotate(VALUE, [SEED])
+~~~
-* `get_module_path`: Returns the absolute path of the specified module for the current environment.
+*Examples:*
+
+~~~
+fqdn_rotate(['a', 'b', 'c', 'd'])
+fqdn_rotate('abcd')
+fqdn_rotate([1, 2, 3], 'custom seed')
+~~~
+
+*Type*: rvalue.
+
+#### `fqdn_uuid`
+
+Returns a rfc4122 valid version 5 UUID based on an FQDN string under the DNS namespace
+
+ * fqdn_uuid('puppetlabs.com') returns '9c70320f-6815-5fc5-ab0f-debe68bf764c'
+ * fqdn_uuid('google.com') returns '64ee70a4-8cc1-5d25-abf2-dea6c79a09c8'
+
+*Type*: rvalue.
+
+#### `get_module_path`
+
+Returns the absolute path of the specified module for the current environment.
`$module_path = get_module_path('stdlib')`
- *Type*: rvalue
+*Type*: rvalue.
+
+#### `getparam`
-* `getparam`: Takes a resource reference and the name of the parameter and
-returns the value of the resource's parameter. For example, the following code returns 'param_value'.
+Takes a resource reference and the name of the parameter, and returns the value of the resource's parameter.
- *Example:*
+For example, the following returns 'param_value':
- ```
+ ~~~
define example_resource($param) {
}
@@ -217,61 +610,73 @@ returns the value of the resource's parameter. For example, the following code r
}
getparam(Example_resource["example_resource_instance"], "param")
- ```
+ ~~~
+
+*Type*: rvalue.
- *Type*: rvalue
+#### `getvar`
-* `getvar`: Lookup a variable in a remote namespace.
+Looks up a variable in a remote namespace.
- For example:
+For example:
- ```
+ ~~~
$foo = getvar('site::data::foo')
# Equivalent to $foo = $site::data::foo
- ```
+ ~~~
- This is useful if the namespace itself is stored in a string:
+This is useful if the namespace itself is stored in a string:
- ```
+ ~~~
$datalocation = 'site::data'
$bar = getvar("${datalocation}::bar")
# Equivalent to $bar = $site::data::bar
- ```
+ ~~~
- *Type*: rvalue
+*Type*: rvalue.
-* `grep`: This function searches through an array and returns any elements that match the provided regular expression. For example, `grep(['aaa','bbb','ccc','aaaddd'], 'aaa')` returns ['aaa','aaaddd']. *Type*: rvalue
+#### `grep`
-* `has_interface_with`: Returns boolean based on kind and value:
+Searches through an array and returns any elements that match the provided regular expression. For example, `grep(['aaa','bbb','ccc','aaaddd'], 'aaa')` returns ['aaa','aaaddd']. *Type*: rvalue.
+
+#### `has_interface_with`
+
+Returns a boolean based on kind and value:
* macaddress
* netmask
* ipaddress
* network
- *Examples:*
+*Examples:*
- ```
+ ~~~
has_interface_with("macaddress", "x:x:x:x:x:x")
has_interface_with("ipaddress", "127.0.0.1") => true
- ```
+ ~~~
- If no kind is given, then the presence of the interface is checked:
+If no kind is given, then the presence of the interface is checked:
- ```
+ ~~~
has_interface_with("lo") => true
- ```
+ ~~~
+
+*Type*: rvalue.
- *Type*: rvalue
+#### `has_ip_address`
-* `has_ip_address`: Returns true if the client has the requested IP address on some interface. This function iterates through the `interfaces` fact and checks the `ipaddress_IFACE` facts, performing a simple string comparison. *Type*: rvalue
+Returns 'true' if the client has the requested IP address on some interface. This function iterates through the `interfaces` fact and checks the `ipaddress_IFACE` facts, performing a simple string comparison. *Type*: rvalue.
-* `has_ip_network`: Returns true if the client has an IP address within the requested network. This function iterates through the 'interfaces' fact and checks the 'network_IFACE' facts, performing a simple string comparision. *Type*: rvalue
+#### `has_ip_network`
-* `has_key`: Determine if a hash has a certain key value.
+Returns 'true' if the client has an IP address within the requested network. This function iterates through the `interfaces` fact and checks the `network_IFACE` facts, performing a simple string comparision. *Type*: rvalue.
- *Example*:
+#### `has_key`
- ```
+Determines if a hash has a certain key value.
+
+*Example*:
+
+ ~~~
$my_hash = {'key_one' => 'value_one'}
if has_key($my_hash, 'key_two') {
notice('we will not reach here')
@@ -279,137 +684,418 @@ returns the value of the resource's parameter. For example, the following code r
if has_key($my_hash, 'key_one') {
notice('this will be printed')
}
- ```
+ ~~~
+
+*Type*: rvalue.
+
+#### `hash`
+
+Converts an array into a hash. For example, `hash(['a',1,'b',2,'c',3])` returns {'a'=>1,'b'=>2,'c'=>3}. *Type*: rvalue.
+
+#### `intersection`
+
+Returns an array an intersection of two. For example, `intersection(["a","b","c"],["b","c","d"])` returns ["b","c"]. *Type*: rvalue.
+
+#### `is_a`
+
+Boolean check to determine whether a variable is of a given data type. This is equivalent to the `=~` type checks. This function is available only in Puppet 4 or in Puppet 3 with the "future" parser.
+
+ ~~~
+ foo = 3
+ $bar = [1,2,3]
+ $baz = 'A string!'
+
+ if $foo.is_a(Integer) {
+ notify { 'foo!': }
+ }
+ if $bar.is_a(Array) {
+ notify { 'bar!': }
+ }
+ if $baz.is_a(String) {
+ notify { 'baz!': }
+ }
+ ~~~
+
+See the [the Puppet type system](https://docs.puppetlabs.com/references/latest/type.html#about-resource-types) for more information about types.
+See the [`assert_type()`](https://docs.puppetlabs.com/references/latest/function.html#asserttype) function for flexible ways to assert the type of a value.
+
+#### `is_absolute_path`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Returns 'true' if the given path is absolute. *Type*: rvalue.
+
+#### `is_array`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Returns 'true' if the variable passed to this function is an array. *Type*: rvalue.
+
+#### `is_bool`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Returns 'true' if the variable passed to this function is a boolean. *Type*: rvalue.
+
+#### `is_domain_name`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Returns 'true' if the string passed to this function is a syntactically correct domain name. *Type*: rvalue.
+
+#### `is_float`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Returns 'true' if the variable passed to this function is a float. *Type*: rvalue.
+
+#### `is_function_available`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Accepts a string as an argument and determines whether the Puppet runtime has access to a function by that name. It returns 'true' if the function exists, 'false' if not. *Type*: rvalue.
+
+#### `is_hash`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Returns 'true' if the variable passed to this function is a hash. *Type*: rvalue.
+
+#### `is_integer`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Returns 'true' if the variable returned to this string is an integer. *Type*: rvalue.
- *Type*: rvalue
+#### `is_ip_address`
-* `hash`: This function converts an array into a hash. For example, `hash(['a',1,'b',2,'c',3])` returns {'a'=>1,'b'=>2,'c'=>3}. *Type*: rvalue
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
-* `intersection`: This function returns an array an intersection of two. For example, `intersection(["a","b","c"],["b","c","d"])` returns ["b","c"].
+Returns 'true' if the string passed to this function is a valid IP address. *Type*: rvalue.
-* `is_array`: Returns 'true' if the variable passed to this function is an array. *Type*: rvalue
+#### `is_ipv6_address`
-* `is_bool`: Returns 'true' if the variable passed to this function is a boolean. *Type*: rvalue
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
-* `is_domain_name`: Returns 'true' if the string passed to this function is a syntactically correct domain name. *Type*: rvalue
+Returns 'true' if the string passed to this function is a valid IPv6 address. *Type*: rvalue.
-* `is_float`: Returns 'true' if the variable passed to this function is a float. *Type*: rvalue
+#### `is_ipv4_address`
-* `is_function_available`: This function accepts a string as an argument and determines whether the Puppet runtime has access to a function by that name. It returns 'true' if the function exists, 'false' if not. *Type*: rvalue
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
-* `is_hash`: Returns 'true' if the variable passed to this function is a hash. *Type*: rvalue
+Returns 'true' if the string passed to this function is a valid IPv4 address. *Type*: rvalue.
-* `is_integer`: Returns 'true' if the variable returned to this string is an integer. *Type*: rvalue
+#### `is_mac_address`
-* `is_ip_address`: Returns 'true' if the string passed to this function is a valid IP address. *Type*: rvalue
+Returns 'true' if the string passed to this function is a valid MAC address. *Type*: rvalue.
-* `is_mac_address`: Returns 'true' if the string passed to this function is a valid MAC address. *Type*: rvalue
+#### `is_numeric`
-* `is_numeric`: Returns 'true' if the variable passed to this function is a number. *Type*: rvalue
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
-* `is_string`: Returns 'true' if the variable passed to this function is a string. *Type*: rvalue
+Returns 'true' if the variable passed to this function is a number. *Type*: rvalue.
-* `join`: This function joins an array into a string using a separator. For example, `join(['a','b','c'], ",")` results in: "a,b,c". *Type*: rvalue
+#### `is_string`
-* `join_keys_to_values`: This function joins each key of a hash to that key's corresponding value with a separator. Keys and values are cast to strings. The return value is an array in which each element is one joined key/value pair. For example, `join_keys_to_values({'a'=>1,'b'=>2}, " is ")` results in ["a is 1","b is 2"]. *Type*: rvalue
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
-* `keys`: Returns the keys of a hash as an array. *Type*: rvalue
+Returns 'true' if the variable passed to this function is a string. *Type*: rvalue.
-* `loadyaml`: Load a YAML file containing an array, string, or hash, and return the data in the corresponding native data type. For example:
+#### `join`
- ```
+Joins an array into a string using a separator. For example, `join(['a','b','c'], ",")` results in: "a,b,c". *Type*: rvalue.
+
+#### `join_keys_to_values`
+
+Joins each key of a hash to that key's corresponding value with a separator. Keys are cast to strings.
+If values are arrays, multiple keys are added for each element.
+The return value is an array in which each element is one joined key/value pair. For example, `join_keys_to_values({'a'=>1,'b'=>[2,3]}, " is ")` results in ["a is 1","b is 2","b is 3"]. *Type*: rvalue.
+
+#### `keys`
+
+Returns the keys of a hash as an array. *Type*: rvalue.
+
+#### `loadyaml`
+
+Loads a YAML file containing an array, string, or hash, and returns the data in the corresponding native data type.
+
+For example:
+
+ ~~~
$myhash = loadyaml('/etc/puppet/data/myhash.yaml')
- ```
+ ~~~
+
+The second parameter will be returned if the file was not found or could not be parsed.
+
+For example:
+
+ ~~~
+ $myhash = loadyaml('no-file.yaml', {'default'=>'value'})
+ ~~~
+
+*Type*: rvalue.
+
+#### `loadjson`
+
+Loads a JSON file containing an array, string, or hash, and returns the data in the corresponding native data type.
+
+For example:
+
+ ~~~
+ $myhash = loadjson('/etc/puppet/data/myhash.json')
+ ~~~
+
+The second parameter will be returned if the file was not found or could not be parsed.
+
+For example:
+
+ ~~~
+ $myhash = loadjson('no-file.json', {'default'=>'value'})
+ ~~~
+
+*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']: }
+ ~~~
+
+If you do not want to fail the catalog compilation when a module's metadata file is absent:
+
+ ~~~
+ $metadata = load_module_metadata('mysql', true)
+ if empty($metadata) {
+ notify { "This module does not have a metadata.json file.": }
+ }
+ ~~~
+
+*Type*: rvalue.
- *Type*: rvalue
+#### `lstrip`
-* `lstrip`: Strips leading spaces to the left of a string. *Type*: rvalue
+Strips spaces to the left of a string. *Type*: rvalue.
-* `max`: Returns the highest value of all arguments. Requires at least one argument. *Type*: rvalue
+#### `max`
-* `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'. *Type*: rvalue
+Returns the highest value of all arguments. Requires at least one argument. *Type*: rvalue.
-* `merge`: Merges two or more hashes together and returns the resulting hash.
+#### `member`
- *Example*:
+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.
+
+#### `merge`
+
+Merges two or more hashes together and returns the resulting hash.
+
+*Example*:
+
+ ~~~
$hash1 = {'one' => 1, 'two' => 2}
$hash2 = {'two' => 'dos', 'three' => 'tres'}
$merged_hash = merge($hash1, $hash2)
# The resulting hash is equivalent to:
# $merged_hash = {'one' => 1, 'two' => 'dos', 'three' => 'tres'}
- ```
+ ~~~
+
+When there is a duplicate key, the key in the rightmost hash "wins." *Type*: rvalue.
+
+#### `min`
+
+Returns the lowest value of all arguments. Requires at least one argument. *Type*: rvalue.
- When there is a duplicate key, the key in the rightmost hash "wins." *Type*: rvalue
+#### `num2bool`
-* `min`: Returns the lowest value of all arguments. Requires at least one argument. *Type*: rvalue
+Converts a number or a string representation of a number into a true boolean. Zero or anything non-numeric becomes 'false'. Numbers greater than 0 become 'true'. *Type*: rvalue.
-* `num2bool`: This function converts a number or a string representation of a number into a true boolean. Zero or anything non-numeric becomes 'false'. Numbers greater than 0 become 'true'. *Type*: rvalue
+#### `parsejson`
-* `parsejson`: This function accepts JSON as a string and converts into the correct Puppet structure. *Type*: rvalue
+Converts a string of JSON into the correct Puppet structure. *Type*: rvalue. The optional second argument is returned if the data was not correct.
-* `parseyaml`: This function accepts YAML as a string and converts it into the correct Puppet structure. *Type*: rvalue
+#### `parseyaml`
-* `pick`: From a list of values, returns the first value that is not undefined or an empty string. Takes any number of arguments, and raises an error if all values are undefined or empty.
+Converts a string of YAML into the correct Puppet structure. *Type*: rvalue. The optional second argument is returned if the data was not correct.
- ```
+#### `pick`
+
+From a list of values, returns the first value that is not undefined or an empty string. Takes any number of arguments, and raises an error if all values are undefined or empty.
+
+ ~~~
$real_jenkins_version = pick($::jenkins_version, '1.449')
- ```
+ ~~~
+
+*Type*: rvalue.
+
+#### `pick_default`
+
+Returns the first value in a list of values. Contrary to the `pick()` function, the `pick_default()` does not fail if all arguments are empty. This allows it to use an empty value as default. *Type*: rvalue.
+
+#### `prefix`
- *Type*: rvalue
+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`: This function applies a prefix to all elements in an array. For example, `prefix(['a','b','c'], 'p')` returns ['pa','pb','pc']. *Type*: rvalue
+*Type*: rvalue.
+#### `pry`
-* `private`: This function sets the current class or definition as private.
-Calling the class or definition from outside the current module will fail. For example, `private()` called in class `foo::bar` outputs the following message if class is called from outside module `foo`:
+This function invokes a pry debugging session in the current scope object. This is useful for debugging manifest code at specific points during a compilation. Should only be used when running `puppet apply` or running a puppet master in the foreground. This requires the `pry` gem to be installed in puppet's rubygems.
- ```
+*Examples:*
+```puppet
+pry()
+```
+Once in a pry session, some interesting commands:
+
+* Run `catalog` to see the contents currently compiling catalog
+* Run `cd catalog` and `ls` to see catalog methods and instance variables
+* Run `@resource_table` to see the current catalog resource table
+
+#### `assert_private`
+
+Sets the current class or definition as private. Calling the class or definition from outside the current module will fail.
+
+For example, `assert_private()` called in class `foo::bar` outputs the following message if class is called from outside module `foo`:
+
+ ~~~
Class foo::bar is private
- ```
+ ~~~
+
+ To specify the error message you want to use:
+
+ ~~~
+ assert_private("You're not supposed to do that!")
+ ~~~
+
+*Type*: statement.
+
+#### `pw_hash`
+
+Hashes a password using the crypt function. Provides a hash usable on most POSIX systems.
+
+The first argument to this function is the password to hash. If it is undef or an empty string, this function returns undef.
+
+The second argument to this function is which type of hash to use. It will be converted into the appropriate crypt(3) hash specifier. Valid hash types are:
+
+|Hash type |Specifier|
+|---------------------|---------|
+|MD5 |1 |
+|SHA-256 |5 |
+|SHA-512 (recommended)|6 |
- You can specify the error message you want to use:
+The third argument to this function is the salt to use.
- ```
- private("You're not supposed to do that!")
- ```
+*Type*: rvalue.
- *Type*: statement
+**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`: When given range in the form of '(start, stop)', `range` extrapolates a range as an array. For example, `range("0", "9")` returns [0,1,2,3,4,5,6,7,8,9]. Zero-padded strings are converted to integers automatically, so `range("00", "09")` returns [0,1,2,3,4,5,6,7,8,9].
+#### `range`
- Non-integer strings are accepted; `range("a", "c")` returns ["a","b","c"], and `range("host01", "host10")` returns ["host01", "host02", ..., "host09", "host10"].
+Extrapolates a range as an array when given in the form of '(start, stop)'. For example, `range("0", "9")` returns [0,1,2,3,4,5,6,7,8,9]. Zero-padded strings are converted to integers automatically, so `range("00", "09")` returns [0,1,2,3,4,5,6,7,8,9].
- *Type*: rvalue
+Non-integer strings are accepted; `range("a", "c")` returns ["a","b","c"], and `range("host01", "host10")` returns ["host01", "host02", ..., "host09", "host10"].
+NB Be explicit in including trailing zeros. Otherwise the underlying ruby function will fail.
-* `reject`: This function searches through an array and rejects all elements that match the provided regular expression. For example, `reject(['aaa','bbb','ccc','aaaddd'], 'aaa')` returns ['bbb','ccc']. *Type*: rvalue
+Passing a third argument will cause the generated range to step by that interval, e.g. `range("0", "9", "2")` returns ["0","2","4","6","8"].
-* `reverse`: Reverses the order of a string or array. *Type*: rvalue
+*Type*: rvalue.
-* `rstrip`: Strips leading spaces to the right of the string.*Type*: rvalue
+#### `regexpescape`
-* `shuffle`: Randomizes the order of a string or array elements. *Type*: rvalue
+Regexp escape a string or array of strings. Requires either a single string or an array as an input. *Type*: rvalue.
-* `size`: Returns the number of elements in a string or array. *Type*: rvalue
+#### `reject`
-* `sort`: Sorts strings and arrays lexically. *Type*: rvalue
+Searches through an array and rejects all elements that match the provided regular expression. For example, `reject(['aaa','bbb','ccc','aaaddd'], 'aaa')` returns ['bbb','ccc']. *Type*: rvalue.
-* `squeeze`: Returns a new string where runs of the same character that occur in this set are replaced by a single character. *Type*: rvalue
+#### `reverse`
-* `str2bool`: This converts a string to a boolean. This attempts to convert strings that contain values such as '1', 't', 'y', and 'yes' to 'true' and strings that contain values such as '0', 'f', 'n', and 'no' to 'false'. *Type*: rvalue
+Reverses the order of a string or array. *Type*: rvalue.
-* `str2saltedsha512`: This converts a string to a salted-SHA512 password hash, used for OS X versions >= 10.7. Given any string, this function returns a hex version of a salted-SHA512 password hash, which can be inserted into your Puppet
-manifests as a valid password attribute. *Type*: rvalue
+#### `rstrip`
-* `strftime`: This function returns formatted time. For example, `strftime("%s")` returns the time since epoch, and `strftime("%Y=%m-%d")` returns the date. *Type*: rvalue
+Strips spaces to the right of the string. *Type*: rvalue.
+
+#### `seeded_rand`
+
+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.
+
+#### `size`
+
+Returns the number of elements in a string, an array or a hash. *Type*: rvalue.
+
+#### `sort`
+
+Sorts strings and arrays lexically. *Type*: rvalue.
+
+#### `squeeze`
+
+Returns a new string where runs of the same character that occur in this set are replaced by a single character. *Type*: rvalue.
+
+#### `str2bool`
+
+Converts certain strings to a boolean. This attempts to convert strings that contain the values '1', 'true', 't', 'y', or 'yes' to true. Strings that contain values '0', 'false', 'f', 'n', or 'no', or that are an empty string or undefined are converted to false. Any other value causes an error. These checks are case insensitive. *Type*: rvalue.
+
+#### `str2saltedsha512`
+
+Converts a string to a salted-SHA512 password hash, used for OS X versions >= 10.7. Given any string, this function returns a hex version of a salted-SHA512 password hash, which can be inserted into your Puppet
+manifests as a valid password attribute. *Type*: rvalue.
+
+#### `strftime`
+
+Returns formatted time. For example, `strftime("%s")` returns the time since Unix epoch, and `strftime("%Y-%m-%d")` returns the date. *Type*: rvalue.
*Format:*
* `%a`: The abbreviated weekday name ('Sun')
- * `%A`: The full weekday name ('Sunday')
+ * `%A`: The full weekday name ('Sunday')
* `%b`: The abbreviated month name ('Jan')
- * `%B`: The full month name ('January')
+ * `%B`: The full month name ('January')
* `%c`: The preferred local date and time representation
* `%C`: Century (20 in 2009)
* `%d`: Day of the month (01..31)
@@ -430,271 +1116,592 @@ manifests as a valid password attribute. *Type*: rvalue
* `%3N`: Millisecond (3 digits)
* `%6N`: Microsecond (6 digits)
* `%9N`: Nanosecond (9 digits)
- * `%p`: Meridian indicator ('AM' or 'PM')
- * `%P`: Meridian indicator ('am' or 'pm')
+ * `%p`: Meridian indicator ('AM' or 'PM')
+ * `%P`: Meridian indicator ('am' or 'pm')
* `%r`: Time, 12-hour (same as %I:%M:%S %p)
* `%R`: Time, 24-hour (%H:%M)
- * `%s`: Number of seconds since 1970-01-01 00:00:00 UTC.
+ * `%s`: Number of seconds since the Unix epoch, 1970-01-01 00:00:00 UTC.
* `%S`: Second of the minute (00..60)
* `%t`: Tab character ( )
* `%T`: Time, 24-hour (%H:%M:%S)
* `%u`: Day of the week as a decimal, Monday being 1. (1..7)
- * `%U`: Week number of the current year, starting with the first Sunday as the first day of the first week (00..53)
+ * `%U`: Week number of the current year, starting with the first Sunday as the first day of the first week (00..53)
* `%v`: VMS date (%e-%b-%Y)
* `%V`: Week number of year according to ISO 8601 (01..53)
- * `%W`: Week number of the current year, starting with the first Monday as the first day of the first week (00..53)
+ * `%W`: Week number of the current year, starting with the first Monday as the first day of the first week (00..53)
* `%w`: Day of the week (Sunday is 0, 0..6)
* `%x`: Preferred representation for the date alone, no time
* `%X`: Preferred representation for the time alone, no date
* `%y`: Year without a century (00..99)
* `%Y`: Year with century
- * `%z`: Time zone as hour offset from UTC (e.g. +0900)
+ * `%z`: Time zone as hour offset from UTC (e.g. +0900)
* `%Z`: Time zone name
* `%%`: Literal '%' character
+#### `strip`
-* `strip`: This function removes leading and trailing whitespace from a string or from every string inside an array. For example, `strip(" aaa ")` results in "aaa". *Type*: rvalue
+Removes leading and trailing whitespace from a string or from every string inside an array. For example, `strip(" aaa ")` results in "aaa". *Type*: rvalue.
-* `suffix`: This function applies a suffix to all elements in an array. For example, `suffix(['a','b','c'], 'p')` returns ['ap','bp','cp']. *Type*: rvalue
+#### `suffix`
-* `swapcase`: This function swaps the existing case of a string. For example, `swapcase("aBcD")` results in "AbCd". *Type*: rvalue
+Applies a suffix to all elements in an array, or to the keys in a hash.
+For example:
+* `suffix(['a','b','c'], 'p')` returns ['ap','bp','cp']
+* `suffix({'a'=>'b','b'=>'c','c'=>'d'}, 'p')` returns {'ap'=>'b','bp'=>'c','cp'=>'d'}.
-* `time`: This function returns the current time since epoch as an integer. For example, `time()` returns something like '1311972653'. *Type*: rvalue
+*Type*: rvalue.
-* `to_bytes`: Converts the argument into bytes, for example 4 kB becomes 4096.
-Takes a single string value as an argument. *Type*: rvalue
+#### `swapcase`
-* `type3x`: Returns a string description of the type when passed a value. Type can be a string, array, hash, float, integer, or boolean. This function will be removed when puppet 3 support is dropped and the new type system may be used. *Type*: rvalue
+Swaps the existing case of a string. For example, `swapcase("aBcD")` results in "AbCd". *Type*: rvalue.
-* `type_of`: Returns the literal type when passed a value. Requires the new
- parser. Useful for comparison of types with `<=` such as in `if
- type_of($some_value) <= Array[String] { ... }` (which is equivalent to `if
- $some_value =~ Array[String] { ... }`) *Type*: rvalue
+#### `time`
-* `union`: This function returns a union of two arrays. For example, `union(["a","b","c"],["b","c","d"])` returns ["a","b","c","d"].
+Returns the current Unix epoch time as an integer. For example, `time()` returns something like '1311972653'. *Type*: rvalue.
-* `unique`: This function removes duplicates from strings and arrays. For example, `unique("aabbcc")` returns 'abc'.
+#### `to_bytes`
-You can also use this with arrays. For example, `unique(["a","a","b","b","c","c"])` returns ["a","b","c"]. *Type*: rvalue
+Converts the argument into bytes, for example "4 kB" becomes "4096". Takes a single string value as an argument. *Type*: rvalue.
-* `upcase`: Converts a string or an array of strings to uppercase. For example, `upcase("abcd")` returns 'ABCD'. *Type*: rvalue
+#### `try_get_value`
-* `uriescape`: Urlencodes a string or array of strings. Requires either a single string or an array as an input. *Type*: rvalue
+*Type*: rvalue.
-* `validate_absolute_path`: Validate the string represents an absolute path in the filesystem. This function works for Windows and Unix style paths.
+DEPRECATED: replaced by `dig()`.
- The following values will pass:
+Retrieves a value within multiple layers of hashes and arrays via a string containing a path. The path is a string of hash keys or array indexes starting with zero, separated by the path separator character (default "/"). The function goes through the structure by each path component and tries to return the value at the end of the path.
- ```
- $my_path = 'C:/Program Files (x86)/Puppet Labs/Puppet'
- validate_absolute_path($my_path)
- $my_path2 = '/var/lib/puppet'
- validate_absolute_path($my_path2)
- $my_path3 = ['C:/Program Files (x86)/Puppet Labs/Puppet','C:/Program Files/Puppet Labs/Puppet']
- validate_absolute_path($my_path3)
- $my_path4 = ['/var/lib/puppet','/usr/share/puppet']
- validate_absolute_path($my_path4)
- ```
+In addition to the required path argument, the function accepts the default argument. It is returned if the path is not correct, if no value was found, or if any other error has occurred. The last argument can set the path separator character.
- The following values will fail, causing compilation to abort:
+~~~ruby
+$data = {
+ 'a' => {
+ 'b' => [
+ 'b1',
+ 'b2',
+ 'b3',
+ ]
+ }
+}
- ```
- validate_absolute_path(true)
- validate_absolute_path('../var/lib/puppet')
- validate_absolute_path('var/lib/puppet')
- validate_absolute_path([ 'var/lib/puppet', '/var/foo' ])
- validate_absolute_path([ '/var/lib/puppet', 'var/foo' ])
- $undefined = undef
- validate_absolute_path($undefined)
- ```
+$value = try_get_value($data, 'a/b/2')
+# $value = 'b3'
- *Type*: statement
+# with all possible options
+$value = try_get_value($data, 'a/b/2', 'not_found', '/')
+# $value = 'b3'
-* `validate_array`: Validate that all passed values are array data structures. Abort catalog compilation if any value fails this check.
+# using the default value
+$value = try_get_value($data, 'a/b/c/d', 'not_found')
+# $value = 'not_found'
- The following values will pass:
+# using custom separator
+$value = try_get_value($data, 'a|b', [], '|')
+# $value = ['b1','b2','b3']
+~~~
- ```
- $my_array = [ 'one', 'two' ]
- validate_array($my_array)
- ```
+1. **$data** The data structure we are working with.
+2. **'a/b/2'** The path string.
+3. **'not_found'** The default value. It will be returned if nothing is found.
+ (optional, defaults to *undef*)
+4. **'/'** The path separator character.
+ (optional, defaults to *'/'*)
- The following values will fail, causing compilation to abort:
+#### `type3x`
- ```
- validate_array(true)
- validate_array('some_string')
- $undefined = undef
- validate_array($undefined)
- ```
+Returns a string description of the type when passed a value. Type can be a string, array, hash, float, integer, or boolean. This function will be removed when Puppet 3 support is dropped and the new type system can be used. *Type*: rvalue.
- *Type*: statement
+#### `type_of`
-* `validate_augeas`: Performs validation of a string using an Augeas lens.
-The first argument of this function should be the string to test, and the second argument should be the name of the Augeas lens to use. If Augeas fails to parse the string with the lens, the compilation aborts with a parse error.
+This function is provided for backwards compatibility but is generally not preferred over the built-in [type() function](https://docs.puppet.com/puppet/latest/reference/function.html#type) provided by Puppet.
- A third optional argument lists paths which should **not** be found in the file. The `$file` variable points to the location of the temporary file being tested in the Augeas tree.
+Returns the literal type when passed a value. Requires the new parser. Useful for comparison of types with `<=` such as in `if type_of($some_value) <= Array[String] { ... }` (which is equivalent to `if $some_value =~ Array[String] { ... }`) *Type*: rvalue.
- For example, to make sure your passwd content never contains user `foo`:
+#### `union`
- ```
- validate_augeas($passwdcontent, 'Passwd.lns', ['$file/foo'])
- ```
+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.
- To ensure that no users use the '/bin/barsh' shell:
+#### `unique`
- ```
- validate_augeas($passwdcontent, 'Passwd.lns', ['$file/*[shell="/bin/barsh"]']
- ```
+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.
- You can pass a fourth argument as the error message raised and shown to the user:
+#### `unix2dos`
- ```
- validate_augeas($sudoerscontent, 'Sudoers.lns', [], 'Failed to validate sudoers content with Augeas')
- ```
+Returns the DOS version of the given string. Very useful when using a File resource with a cross-platform template. *Type*: rvalue.
- *Type*: statement
+~~~
+file{$config_file:
+ ensure => file,
+ content => unix2dos(template('my_module/settings.conf.erb')),
+}
+~~~
-* `validate_bool`: Validate that all passed values are either true or false. Abort catalog compilation if any value fails this check.
+See also [dos2unix](#dos2unix).
- The following values will pass:
+#### `upcase`
- ```
- $iamtrue = true
- validate_bool(true)
- validate_bool(true, true, false, $iamtrue)
- ```
+Converts an object, array or hash of objects that respond to upcase to uppercase. For example, `upcase('abcd')` returns 'ABCD'. *Type*: rvalue.
- The following values will fail, causing compilation to abort:
+#### `uriescape`
+
+URLEncodes a string or array of strings. Requires either a single string or an array as an input. *Type*: rvalue.
+
+#### `validate_absolute_path`
+
+Validates that a given string represents an absolute path in the filesystem. Works for Windows and Unix style paths.
+
+The following values pass:
+
+~~~
+$my_path = 'C:/Program Files (x86)/Puppet Labs/Puppet'
+validate_absolute_path($my_path)
+$my_path2 = '/var/lib/puppet'
+validate_absolute_path($my_path2)
+$my_path3 = ['C:/Program Files (x86)/Puppet Labs/Puppet','C:/Program Files/Puppet Labs/Puppet']
+validate_absolute_path($my_path3)
+$my_path4 = ['/var/lib/puppet','/usr/share/puppet']
+validate_absolute_path($my_path4)
+~~~
+
+The following values fail, causing compilation to abort:
+
+~~~
+validate_absolute_path(true)
+validate_absolute_path('../var/lib/puppet')
+validate_absolute_path('var/lib/puppet')
+validate_absolute_path([ 'var/lib/puppet', '/var/foo' ])
+validate_absolute_path([ '/var/lib/puppet', 'var/foo' ])
+$undefined = undef
+validate_absolute_path($undefined)
+~~~
+
+*Type*: statement.
+
+#### `validate_array`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Validates that all passed values are array data structures. Aborts catalog compilation if any value fails this check.
+
+The following values pass:
+
+~~~
+$my_array = [ 'one', 'two' ]
+validate_array($my_array)
+~~~
+
+The following values fail, causing compilation to abort:
+
+~~~
+validate_array(true)
+validate_array('some_string')
+$undefined = undef
+validate_array($undefined)
+~~~
+
+*Type*: statement.
+
+#### `validate_augeas`
+
+Performs validation of a string using an Augeas lens. The first argument of this function should be the string to test, and the second argument should be the name of the Augeas lens to use. If Augeas fails to parse the string with the lens, the compilation aborts with a parse error.
- ```
- $some_array = [ true ]
- validate_bool("false")
- validate_bool("true")
- validate_bool($some_array)
- ```
+A third optional argument lists paths which should **not** be found in the file. The `$file` variable points to the location of the temporary file being tested in the Augeas tree.
- *Type*: statement
+For example, to make sure your $passwdcontent never contains user `foo`:
-* `validate_cmd`: Performs validation of a string with an external command. The first argument of this function should be a string to test, and the second argument should be a path to a test command taking a % as a placeholder for the file path (will default to the end of the command if no % placeholder given). If the command, launched against a tempfile containing the passed string, returns a non-null value, compilation will abort with a parse error.
+~~~
+validate_augeas($passwdcontent, 'Passwd.lns', ['$file/foo'])
+~~~
+
+To ensure that no users use the '/bin/barsh' shell:
+
+~~~
+validate_augeas($passwdcontent, 'Passwd.lns', ['$file/*[shell="/bin/barsh"]']
+~~~
+
+You can pass a fourth argument as the error message raised and shown to the user:
+
+~~~
+validate_augeas($sudoerscontent, 'Sudoers.lns', [], 'Failed to validate sudoers content with Augeas')
+~~~
+
+*Type*: statement.
+
+#### `validate_bool`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Validates that all passed values are either true or false. Aborts catalog compilation if any value fails this check.
+
+The following values will pass:
+
+~~~
+$iamtrue = true
+validate_bool(true)
+validate_bool(true, true, false, $iamtrue)
+~~~
+
+The following values will fail, causing compilation to abort:
+
+~~~
+$some_array = [ true ]
+validate_bool("false")
+validate_bool("true")
+validate_bool($some_array)
+~~~
+
+*Type*: statement.
+
+#### `validate_cmd`
+
+Performs validation of a string with an external command. The first argument of this function should be a string to test, and the second argument should be a path to a test command taking a % as a placeholder for the file path (will default to the end of the command if no % placeholder given). If the command is launched against a tempfile containing the passed string, or returns a non-null value, compilation will abort with a parse error.
If a third argument is specified, this will be the error message raised and seen by the user.
- ```
- # Defaults to end of path
- validate_cmd($sudoerscontent, '/usr/sbin/visudo -c -f', 'Visudo failed to validate sudoers content')
- ```
- ```
- # % as file location
- validate_cmd($haproxycontent, '/usr/sbin/haproxy -f % -c', 'Haproxy failed to validate config content')
- ```
+~~~
+# Defaults to end of path
+validate_cmd($sudoerscontent, '/usr/sbin/visudo -c -f', 'Visudo failed to validate sudoers content')
+~~~
+~~~
+# % as file location
+validate_cmd($haproxycontent, '/usr/sbin/haproxy -f % -c', 'Haproxy failed to validate config content')
+~~~
+
+*Type*: statement.
- *Type*: statement
+#### `validate_hash`
-* `validate_hash`: Validates that all passed values are hash data structures. Abort catalog compilation if any value fails this check.
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Validates that all passed values are hash data structures. Aborts catalog compilation if any value fails this check.
The following values will pass:
- ```
+ ~~~
$my_hash = { 'one' => 'two' }
validate_hash($my_hash)
- ```
+ ~~~
The following values will fail, causing compilation to abort:
- ```
+ ~~~
validate_hash(true)
validate_hash('some_string')
$undefined = undef
validate_hash($undefined)
- ```
+ ~~~
+
+*Type*: statement.
+
+#### `validate_integer`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Validates that the first argument is an integer (or an array of integers). Aborts catalog compilation if any of the checks fail.
+
+ The second argument is optional and passes a maximum. (All elements of) the first argument has to be less or equal to this max.
+
+ The third argument is optional and passes a minimum. (All elements of) the first argument has to be greater or equal to this min.
+ If, and only if, a minimum is given, the second argument may be an empty string or undef, which will be handled to just check
+ if (all elements of) the first argument are greater or equal to the given minimum.
+
+ It will fail if the first argument is not an integer or array of integers, and if arg 2 and arg 3 are not convertable to an integer.
+
+ The following values will pass:
+
+ ~~~
+ validate_integer(1)
+ validate_integer(1, 2)
+ validate_integer(1, 1)
+ validate_integer(1, 2, 0)
+ validate_integer(2, 2, 2)
+ validate_integer(2, '', 0)
+ validate_integer(2, undef, 0)
+ $foo = undef
+ validate_integer(2, $foo, 0)
+ validate_integer([1,2,3,4,5], 6)
+ validate_integer([1,2,3,4,5], 6, 0)
+ ~~~
+
+ * Plus all of the above, but any combination of values passed as strings ('1' or "1").
+ * Plus all of the above, but with (correct) combinations of negative integer values.
+
+ The following values will fail, causing compilation to abort:
+
+ ~~~
+ validate_integer(true)
+ validate_integer(false)
+ validate_integer(7.0)
+ validate_integer({ 1 => 2 })
+ $foo = undef
+ validate_integer($foo)
+ validate_integer($foobaridontexist)
+
+ validate_integer(1, 0)
+ validate_integer(1, true)
+ validate_integer(1, '')
+ validate_integer(1, undef)
+ validate_integer(1, , 0)
+ validate_integer(1, 2, 3)
+ validate_integer(1, 3, 2)
+ validate_integer(1, 3, true)
+ ~~~
+
+ * 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 items in arrays or maximum / minimum argument.
+
+ *Type*: statement.
+
+#### `validate_ip_address`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Validates that the argument is an IP address, regardless of it is an IPv4 or an IPv6
+address. It also validates IP address with netmask. The argument must be given as a string.
+
+The following values will pass:
+
+ ~~~
+ validate_ip_address('0.0.0.0')
+ validate_ip_address('8.8.8.8')
+ validate_ip_address('127.0.0.1')
+ validate_ip_address('194.232.104.150')
+ validate_ip_address('3ffe:0505:0002::')
+ validate_ip_address('::1/64')
+ validate_ip_address('fe80::a00:27ff:fe94:44d6/64')
+ validate_ip_address('8.8.8.8/32')
+ ~~~
+
+The following values will fail, causing compilation to abort:
+
+ ~~~
+ validate_ip_address(1)
+ validate_ip_address(true)
+ validate_ip_address(0.0.0.256)
+ validate_ip_address('::1', {})
+ validate_ip_address('0.0.0.0.0')
+ validate_ip_address('3.3.3')
+ validate_ip_address('23.43.9.22/64')
+ validate_ip_address('260.2.32.43')
+ ~~~
+
+
+#### `validate_legacy`
+
+Validates a value against both a specified type and a deprecated validation function. Silently passes if both pass, errors if only one validation passes, and fails if both validations return false.
+
+Accepts arguments for:
+* the type to check the value against,
+* the full name of the previous validation function,
+* the value to be checked,
+* an unspecified number of arguments needed for the previous validation function.
+
+Example:
+
+```
+validate_legacy("Optional[String]", "validate_re", "Value to be validated", ["."])
+```
+
+This function supports updating modules from Puppet 3 style argument validation (using the stdlib `validate_*` functions) to Puppet 4 data types, without breaking functionality for those depending on Puppet 3 style validation.
+
+> Note: This function is compatible only with Puppet 4.4.0 (PE 2016.1) and later.
+
+##### For module users
+
+If you are running Puppet 4, the `validate_legacy` function can help you find and resolve deprecated Puppet 3 `validate_*` functions. These functions are deprecated as of stdlib version 4.13 and will be removed in a future version of stdlib.
+
+Puppet 4 allows improved defined type checking using [data types](https://docs.puppet.com/puppet/latest/reference/lang_data.html). Data types avoid some of the problems with Puppet 3's `validate_*` functions, which could sometimes be inconsistent. For example, [validate_numeric](#validate_numeric) unintentionally allowed not only numbers, but also arrays of numbers or strings that looked like numbers.
+
+If you run Puppet 4 and use modules with deprecated `validate_*` functions, you might encounter deprecation messages. The `validate_legacy` function makes these differences visible and makes it easier to move to the clearer Puppet 4 syntax.
+
+The deprecation messages you get can vary, depending on the modules and data that you use. These deprecation messages appear by default only in Puppet 4:
- *Type*: statement
+* `Notice: Accepting previously invalid value for target type '<type>'`: This message is informational only. You're using values that are allowed by the new type, but would have been invalid by the old validation function.
+* `Warning: This method is deprecated, please use the stdlib validate_legacy function`: The module has not yet upgraded to `validate_legacy`. Use the [deprecation](#deprecation) options to silence warnings for now, or submit a fix with the module's developer. See the information [for module developers](#for-module-developers) below for how to fix the issue.
+* `Warning: validate_legacy(<function>) expected <type> value, got <actual type>_`: Your code passes a value that was accepted by the Puppet 3-style validation, but will not be accepted by the next version of the module. Most often, you can fix this by removing quotes from numbers or booleans.
+* `Error: Evaluation Error: Error while evaluating a Resource Statement, Evaluation Error: Error while evaluating a Function Call, validate_legacy(<function>) expected <type> value, got <actual type>`: Your code passes a value that is not acceptable to either the new or the old style validation.
-* `validate_re`: Performs simple validation of a string against one or more regular expressions. The first argument of this function should be the string to
-test, and the second argument should be a stringified regular expression
-(without the // delimiters) or an array of regular expressions. If none
-of the regular expressions match the string passed in, compilation aborts with a parse error.
+##### For module developers
+
+The `validate_legacy` function helps you move from Puppet 3 style validation to Puppet 4 validation without breaking functionality your module's users depend on.
+
+Moving to Puppet 4 type validation allows much better defined type checking using [data types](https://docs.puppet.com/puppet/latest/reference/lang_data.html). Many of Puppet 3's `validate_*` functions have surprising holes in their validation. For example, [validate_numeric](#validate_numeric) allows not only numbers, but also arrays of numbers or strings that look like numbers, without giving you any control over the specifics.
+
+For each parameter of your classes and defined types, choose a new Puppet 4 data type to use. In most cases, the new data type allows a different set of values than the original `validate_*` function. The situation then looks like this:
+
+| | `validate_` pass | `validate_` fail |
+| ------------ | ---------------- | ---------------- |
+| matches type | pass | pass, notice |
+| fails type | pass, deprecated | fail |
+
+The code after the validation still has to handle all possible values for now, but users of your code can change their manifests to pass only values that match the new type.
+
+For each `validate_*` function in stdlib, there is a matching `Stdlib::Compat::*` type that allows the appropriate set of values. See the documentation in the `types/` directory in the stdlib source code for caveats.
+
+For example, given a class that should accept only numbers, like this:
+
+~~~
+class example($value) {
+ validate_numeric($value)
+~~~
+
+the resulting validation code looks like this:
+
+~~~
+class example(
+ Variant[Stdlib::Compat::Numeric, Numeric] $value
+) {
+ validate_legacy(Numeric, 'validate_numeric', $value)
+~~~
+
+Here, the type of `$value` is defined as `Variant[Stdlib::Compat::Numeric, Numeric]`, which allows any `Numeric` (the new type), as well as all values previously accepted by `validate_numeric` (through `Stdlib::Compat::Numeric`).
+
+The call to `validate_legacy` takes care of triggering the correct log or fail message for you. It requires the new type, the previous validation function name, and all arguments to that function.
+
+If your module still supported Puppet 3, this is a breaking change. Update your `metadata.json` requirements section to indicate that your module no longer supports Puppet 3, and bump the major version of your module. With this change, all existing tests for your module should still pass. Create additional tests for the new possible values.
+
+As a breaking change, this is also a good time to call [`deprecation`](#deprecation) for any parameters you want to get rid of, or to add additional constraints on your parameters.
+
+After releasing this version, you can release another breaking change release where you remove all compat types and all calls to `validate_legacy`. At that time, you can also go through your code and remove any leftovers dealing with the previously possible values.
+
+Always note such changes in your CHANGELOG and README.
+
+#### `validate_numeric`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Validates that the first argument is a numeric value (or an array or string of numeric values). Aborts catalog compilation if any of the checks fail.
+
+ The second argument is optional and passes a maximum. (All elements of) the first argument has to be less or equal to this max.
+
+ The third argument is optional and passes a minimum. (All elements of) the first argument has to be greater or equal to this min.
+ If, and only if, a minimum is given, the second argument may be an empty string or undef, which will be handled to just check
+ if (all elements of) the first argument are greater or equal to the given minimum.
+
+ It will fail if the first argument is not a numeric (Integer or Float) or array of numerics, and if arg 2 and arg 3 are not convertable to a numeric.
+
+ For passing and failing usage, see `validate_integer()`. It is all the same for validate_numeric, yet now floating point values are allowed, too.
+
+*Type*: statement.
+
+#### `validate_re`
+
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Performs simple validation of a string against one or more regular expressions. The first argument of this function should be the string to
+test, and the second argument should be a stringified regular expression (without the // delimiters) or an array of regular expressions. If none of the regular expressions match the string passed in, compilation aborts with a parse error.
You can pass a third argument as the error message raised and shown to the user.
The following strings validate against the regular expressions:
- ```
+ ~~~
validate_re('one', '^one$')
validate_re('one', [ '^one', '^two' ])
- ```
+ ~~~
The following string fails to validate, causing compilation to abort:
- ```
+ ~~~
validate_re('one', [ '^two', '^three' ])
- ```
+ ~~~
To set the error message:
- ```
+ ~~~
validate_re($::puppetversion, '^2.7', 'The $puppetversion fact value does not match 2.7')
- ```
+ ~~~
+
+ Note: Compilation terminates if the first argument is not a string. Always use quotes to force stringification:
+
+ ~~~
+ validate_re("${::operatingsystemmajrelease}", '^[57]$')
+ ~~~
+
+*Type*: statement.
- *Type*: statement
+#### `validate_slength`
-* `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.
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+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 the second argument 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:
- ```
+ ~~~
validate_slength("discombobulate",1)
validate_slength(["discombobulate","thermometer"],5)
- ```
+ validate_slength(["discombobulate","moo"],17,10)
+ ~~~
- *Type*: statement
+*Type*: statement.
-* `validate_string`: Validates that all passed values are string data structures. Aborts catalog compilation if any value fails this check.
+#### `validate_string`
- The following values pass:
+**Deprecated. Will be removed in a future version of stdlib. See [`validate_legacy`](#validate_legacy).**
+
+Validates that all passed values are string data structures. Aborts catalog compilation if any value fails this check.
- ```
+The following values pass:
+
+ ~~~
$my_string = "one two"
validate_string($my_string, 'three')
- ```
+ ~~~
The following values fail, causing compilation to abort:
- ```
+ ~~~
validate_string(true)
validate_string([ 'some', 'array' ])
- $undefined = undef
- validate_string($undefined)
- ```
-
- *Type*: statement
+ ~~~
-* `values`: When given a hash, this function returns the values of that hash.
+*Note:* validate_string(undef) will not fail in this version of the functions API (incl. current and future parser).
- *Examples:*
+Instead, use:
- ```
- $hash = {
- 'a' => 1,
- 'b' => 2,
- 'c' => 3,
+ ~~~
+ if $var == undef {
+ fail('...')
}
- values($hash)
- ```
+ ~~~
+
+*Type*: statement.
+
+#### `validate_x509_rsa_key_pair`
+
+Validates a PEM-formatted X.509 certificate and private key using OpenSSL.
+Verifies that the certficate's signature was created from the supplied key.
- The example above returns [1,2,3].
+Fails catalog compilation if any value fails this check.
- *Type*: rvalue
+Takes two arguments, the first argument must be a X.509 certificate and the
+second must be an RSA private key:
-* `values_at`: Finds value inside an array based on location. The first argument is the array you want to analyze, and the second element can be a combination of:
+ ~~~
+ validate_x509_rsa_key_pair($cert, $key)
+ ~~~
+
+*Type*: statement.
+
+#### `values`
+
+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.
+
+#### `values_at`
+
+Finds values inside an array based on location. The first argument is the array you want to analyze, and the second argument can be a combination of:
* A single numeric index
* A range in the form of 'start-stop' (eg. 4-9)
@@ -702,40 +1709,35 @@ of the regular expressions match the string passed in, compilation aborts with a
For example, `values_at(['a','b','c'], 2)` returns ['c']; `values_at(['a','b','c'], ["0-1"])` returns ['a','b']; and `values_at(['a','b','c','d','e'], [0, "2-3"])` returns ['a','c','d'].
- *Type*: rvalue
+*Type*: rvalue.
+
+#### `zip`
-* `zip`: Takes one element from first array and merges corresponding elements from second array. This generates a sequence of n-element arrays, where n is one more than the count of arguments. For example, `zip(['1','2','3'],['4','5','6'])` results in ["1", "4"], ["2", "5"], ["3", "6"]. *Type*: rvalue
+Takes one element from first array given and merges corresponding elements from second array given. This generates a sequence of n-element arrays, where *n* is one more than the count of arguments. For example, `zip(['1','2','3'],['4','5','6'])` results in ["1", "4"], ["2", "5"], ["3", "6"]. *Type*: rvalue.
-##Limitations
+## Limitations
-As of Puppet Enterprise version 3.7, the stdlib module is no longer included in PE. PE users should install the most recent release of stdlib for compatibility with Puppet modules.
+As of Puppet Enterprise 3.7, the stdlib module is no longer included in PE. PE users should install the most recent release of stdlib for compatibility with Puppet modules.
-###Version Compatibility
+### Version Compatibility
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).
-##Development
+## Development
-Puppet Labs modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We can’t access the huge number of platforms and myriad of hardware, software, and deployment configurations that Puppet is intended to serve.
-
-We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things.
-
-You can read the complete module contribution guide on the [Puppet Labs wiki](http://projects.puppetlabs.com/projects/module-site/wiki/Module_contributing).
+Puppet Labs modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We can’t access the huge number of platforms and myriad hardware, software, and deployment configurations that Puppet is intended to serve. We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. For more information, see our [module contribution guide](https://docs.puppetlabs.com/forge/contributing.html).
To report or research a bug with any part of this module, please go to
-[http://tickets.puppetlabs.com/browse/PUP](http://tickets.puppetlabs.com/browse/PUP).
-
-##Contributors
-
-The list of contributors can be found at: https://github.com/puppetlabs/puppetlabs-stdlib/graphs/contributors
-
-
+[http://tickets.puppetlabs.com/browse/MODULES](http://tickets.puppetlabs.com/browse/MODULES).
+## Contributors
+The list of contributors can be found at: [https://github.com/puppetlabs/puppetlabs-stdlib/graphs/contributors](https://github.com/puppetlabs/puppetlabs-stdlib/graphs/contributors).
diff --git a/Rakefile b/Rakefile
index 4ed1327..3e8d4cb 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,18 +1,38 @@
-require 'rubygems'
-require 'puppetlabs_spec_helper/rake_tasks'
+require 'puppet_blacksmith/rake_tasks'
require 'puppet-lint/tasks/puppet-lint'
-PuppetLint.configuration.send('disable_80chars')
-PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"]
+require 'puppetlabs_spec_helper/rake_tasks'
+
+PuppetLint.configuration.send('relative')
+PuppetLint.configuration.send('disable_documentation')
+PuppetLint.configuration.send('disable_single_quote_string_with_variables')
-desc "Validate manifests, templates, and ruby files in lib."
-task :validate do
- Dir['manifests/**/*.pp'].each do |manifest|
- sh "puppet parser validate --noop #{manifest}"
+desc 'Generate pooler nodesets'
+task :gen_nodeset do
+ require 'beaker-hostgenerator'
+ require 'securerandom'
+ require 'fileutils'
+
+ agent_target = ENV['TEST_TARGET']
+ if ! agent_target
+ STDERR.puts 'TEST_TARGET environment variable is not set'
+ STDERR.puts 'setting to default value of "redhat-64default."'
+ agent_target = 'redhat-64default.'
end
- Dir['lib/**/*.rb'].each do |lib_file|
- sh "ruby -c #{lib_file}"
+
+ master_target = ENV['MASTER_TEST_TARGET']
+ if ! master_target
+ STDERR.puts 'MASTER_TEST_TARGET environment variable is not set'
+ STDERR.puts 'setting to default value of "redhat7-64mdcl"'
+ master_target = 'redhat7-64mdcl'
end
- Dir['templates/**/*.erb'].each do |template|
- sh "erb -P -x -T '-' #{template} | ruby -c"
+
+ targets = "#{master_target}-#{agent_target}"
+ cli = BeakerHostGenerator::CLI.new([targets])
+ nodeset_dir = "tmp/nodesets"
+ nodeset = "#{nodeset_dir}/#{targets}-#{SecureRandom.uuid}.yaml"
+ FileUtils.mkdir_p(nodeset_dir)
+ File.open(nodeset, 'w') do |fh|
+ fh.print(cli.execute)
end
+ puts nodeset
end
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/facter_dot_d.rb b/lib/facter/facter_dot_d.rb
index b058437..5c5fb1f 100644
--- a/lib/facter/facter_dot_d.rb
+++ b/lib/facter/facter_dot_d.rb
@@ -8,7 +8,7 @@
# contains a cache TTL. For foo.sh store the ttl as just
# a number in foo.sh.ttl
#
-# The cache is stored in /tmp/facts_cache.yaml as a mode
+# The cache is stored in $libdir/facts_dot_d.cache as a mode
# 600 file and will have the end result of not calling your
# fact scripts more often than is needed
@@ -48,7 +48,7 @@ class Facter::Util::DotD
end
end
end
- rescue Exception => e
+ rescue StandardError => e
Facter.warn("Failed to handle #{file} as text facts: #{e.class}: #{e}")
end
@@ -65,7 +65,7 @@ class Facter::Util::DotD
setcode { v }
end
end
- rescue Exception => e
+ rescue StandardError => e
Facter.warn("Failed to handle #{file} as json facts: #{e.class}: #{e}")
end
@@ -77,7 +77,7 @@ class Facter::Util::DotD
setcode { v }
end
end
- rescue Exception => e
+ rescue StandardError => e
Facter.warn("Failed to handle #{file} as yaml facts: #{e.class}: #{e}")
end
@@ -106,7 +106,7 @@ class Facter::Util::DotD
end
end
end
- rescue Exception => e
+ rescue StandardError => e
Facter.warn("Failed to handle #{file} as script facts: #{e.class}: #{e}")
Facter.debug(e.backtrace.join("\n\t"))
end
diff --git a/lib/facter/package_provider.rb b/lib/facter/package_provider.rb
new file mode 100644
index 0000000..3a9117f
--- /dev/null
+++ b/lib/facter/package_provider.rb
@@ -0,0 +1,21 @@
+# Fact: package_provider
+#
+# Purpose: Returns the default provider Puppet will choose to manage packages
+# on this system
+#
+# Resolution: Instantiates a dummy package resource and return the provider
+#
+# Caveats:
+#
+require 'puppet/type'
+require 'puppet/type/package'
+
+Facter.add(:package_provider) do
+ setcode do
+ if defined? Gem and Gem::Version.new(Facter.value(:puppetversion).split(' ')[0]) >= Gem::Version.new('3.6')
+ Puppet::Type.type(:package).newpackage(:name => 'dummy', :allow_virtual => 'true')[:provider].to_s
+ else
+ Puppet::Type.type(:package).newpackage(:name => 'dummy')[:provider].to_s
+ end
+ end
+end
diff --git a/lib/facter/pe_version.rb b/lib/facter/pe_version.rb
index 0cc0f64..c9f2181 100644
--- a/lib/facter/pe_version.rb
+++ b/lib/facter/pe_version.rb
@@ -10,8 +10,13 @@
#
Facter.add("pe_version") do
setcode do
- pe_ver = Facter.value("puppetversion").match(/Puppet Enterprise (\d+\.\d+\.\d+)/)
- pe_ver[1] if pe_ver
+ puppet_ver = Facter.value("puppetversion")
+ if puppet_ver != nil
+ pe_ver = puppet_ver.match(/Puppet Enterprise (\d+\.\d+\.\d+)/)
+ pe_ver[1] if pe_ver
+ else
+ nil
+ end
end
end
diff --git a/lib/facter/puppet_settings.rb b/lib/facter/puppet_settings.rb
new file mode 100644
index 0000000..eac9e97
--- /dev/null
+++ b/lib/facter/puppet_settings.rb
@@ -0,0 +1,43 @@
+# These facter facts return the value of the Puppet vardir and environment path
+# settings for the node running puppet or puppet agent. The intent is to
+# enable Puppet modules to automatically have insight into a place where they
+# can place variable data, or for modules running on the puppet master to know
+# where environments are stored.
+#
+# The values should be directly usable in a File resource path attribute.
+#
+begin
+ require 'facter/util/puppet_settings'
+rescue LoadError => e
+ # puppet apply does not add module lib directories to the $LOAD_PATH (See
+ # #4248). It should (in the future) but for the time being we need to be
+ # defensive which is what this rescue block is doing.
+ rb_file = File.join(File.dirname(__FILE__), 'util', 'puppet_settings.rb')
+ load rb_file if File.exists?(rb_file) or raise e
+end
+
+
+# These will be nil if Puppet is not available.
+Facter.add(:puppet_vardir) do
+ setcode do
+ Facter::Util::PuppetSettings.with_puppet do
+ Puppet[:vardir]
+ end
+ end
+end
+
+Facter.add(:puppet_environmentpath) do
+ setcode do
+ Facter::Util::PuppetSettings.with_puppet do
+ Puppet[:environmentpath]
+ end
+ end
+end
+
+Facter.add(:puppet_server) do
+ setcode do
+ Facter::Util::PuppetSettings.with_puppet do
+ Puppet[:server]
+ end
+ end
+end
diff --git a/lib/facter/puppet_vardir.rb b/lib/facter/puppet_vardir.rb
deleted file mode 100644
index 0e6af40..0000000
--- a/lib/facter/puppet_vardir.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# This facter fact returns the value of the Puppet vardir setting for the node
-# running puppet or puppet agent. The intent is to enable Puppet modules to
-# automatically have insight into a place where they can place variable data,
-# regardless of the node's platform.
-#
-# The value should be directly usable in a File resource path attribute.
-
-
-begin
- require 'facter/util/puppet_settings'
-rescue LoadError => e
- # puppet apply does not add module lib directories to the $LOAD_PATH (See
- # #4248). It should (in the future) but for the time being we need to be
- # defensive which is what this rescue block is doing.
- rb_file = File.join(File.dirname(__FILE__), 'util', 'puppet_settings.rb')
- load rb_file if File.exists?(rb_file) or raise e
-end
-
-Facter.add(:puppet_vardir) do
- setcode do
- # This will be nil if Puppet is not available.
- Facter::Util::PuppetSettings.with_puppet do
- Puppet[:vardir]
- end
- end
-end
diff --git a/lib/facter/root_home.rb b/lib/facter/root_home.rb
index b4f87ff..87c7657 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/facter/service_provider.rb b/lib/facter/service_provider.rb
new file mode 100644
index 0000000..a117921
--- /dev/null
+++ b/lib/facter/service_provider.rb
@@ -0,0 +1,17 @@
+# Fact: service_provider
+#
+# Purpose: Returns the default provider Puppet will choose to manage services
+# on this system
+#
+# Resolution: Instantiates a dummy service resource and return the provider
+#
+# Caveats:
+#
+require 'puppet/type'
+require 'puppet/type/service'
+
+Facter.add(:service_provider) do
+ setcode do
+ Puppet::Type.type(:service).newservice(:name => 'dummy')[:provider].to_s
+ end
+end
diff --git a/lib/puppet/functions/deprecation.rb b/lib/puppet/functions/deprecation.rb
new file mode 100644
index 0000000..39d9bc7
--- /dev/null
+++ b/lib/puppet/functions/deprecation.rb
@@ -0,0 +1,29 @@
+# Function to print deprecation warnings, Logs a warning once for a given key. The uniqueness key - can appear once. The msg is the message text including any positional information that is formatted by the user/caller of the method It is affected by the puppet setting 'strict', which can be set to :error (outputs as an error message), :off (no message / error is displayed) and :warning (default, outputs a warning) *Type*: String, String.
+#
+
+Puppet::Functions.create_function(:deprecation) do
+ dispatch :deprecation do
+ param 'String', :key
+ param 'String', :message
+ end
+
+ def deprecation(key, message)
+ if defined? Puppet::Pops::PuppetStack.stacktrace()
+ stacktrace = Puppet::Pops::PuppetStack.stacktrace()
+ file = stacktrace[0]
+ line = stacktrace[1]
+ message = "#{message} at #{file}:#{line}"
+ end
+ # depending on configuration setting of strict
+ case Puppet.settings[:strict]
+ when :off
+ # do nothing
+ when :error
+ fail("deprecation. #{key}. #{message}")
+ else
+ unless ENV['STDLIB_LOG_DEPRECATIONS'] == 'false'
+ Puppet.deprecation_warning(message, key)
+ end
+ end
+ end
+end
diff --git a/lib/puppet/functions/is_a.rb b/lib/puppet/functions/is_a.rb
new file mode 100644
index 0000000..da98b03
--- /dev/null
+++ b/lib/puppet/functions/is_a.rb
@@ -0,0 +1,32 @@
+# Boolean check to determine whether a variable is of a given data type. This is equivalent to the `=~` type checks.
+#
+# @example how to check a data type
+# # check a data type
+# foo = 3
+# $bar = [1,2,3]
+# $baz = 'A string!'
+#
+# if $foo.is_a(Integer) {
+# notify { 'foo!': }
+# }
+# if $bar.is_a(Array) {
+# notify { 'bar!': }
+# }
+# if $baz.is_a(String) {
+# notify { 'baz!': }
+# }
+#
+# See the documentation for "The Puppet Type System" for more information about types.
+# See the `assert_type()` function for flexible ways to assert the type of a value.
+#
+Puppet::Functions.create_function(:is_a) do
+ dispatch :is_a do
+ param 'Any', :value
+ param 'Type', :type
+ end
+
+ def is_a(value, type)
+ # See puppet's lib/puppet/pops/evaluator/evaluator_impl.rb eval_MatchExpression
+ Puppet::Pops::Types::TypeCalculator.instance?(type, value)
+ end
+end
diff --git a/lib/puppet/functions/is_absolute_path.rb b/lib/puppet/functions/is_absolute_path.rb
new file mode 100644
index 0000000..b61064a
--- /dev/null
+++ b/lib/puppet/functions/is_absolute_path.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_absolute_path) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_absolute_path', "This method is deprecated, please use match expressions with Stdlib::Compat::Absolute_Path instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_absolute_path", args)
+ end
+end
diff --git a/lib/puppet/functions/is_array.rb b/lib/puppet/functions/is_array.rb
new file mode 100644
index 0000000..a29fe8a
--- /dev/null
+++ b/lib/puppet/functions/is_array.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_array) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_array', "This method is deprecated, please use match expressions with Stdlib::Compat::Array instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_array", args)
+ end
+end
diff --git a/lib/puppet/functions/is_bool.rb b/lib/puppet/functions/is_bool.rb
new file mode 100644
index 0000000..6e2c22b
--- /dev/null
+++ b/lib/puppet/functions/is_bool.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_bool) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_bool', "This method is deprecated, please use match expressions with Stdlib::Compat::Bool instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_bool", args)
+ end
+end
diff --git a/lib/puppet/functions/is_float.rb b/lib/puppet/functions/is_float.rb
new file mode 100644
index 0000000..c91aa5d
--- /dev/null
+++ b/lib/puppet/functions/is_float.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_float) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_float', "This method is deprecated, please use match expressions with Stdlib::Compat::Float instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_float", args)
+ end
+end
diff --git a/lib/puppet/functions/is_ip_address.rb b/lib/puppet/functions/is_ip_address.rb
new file mode 100644
index 0000000..4c72037
--- /dev/null
+++ b/lib/puppet/functions/is_ip_address.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_ip_address) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_ip_address', "This method is deprecated, please use match expressions with Stdlib::Compat::Ip_address instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_ip_address", args)
+ end
+end
diff --git a/lib/puppet/functions/is_ipv4_address.rb b/lib/puppet/functions/is_ipv4_address.rb
new file mode 100644
index 0000000..97b01ae
--- /dev/null
+++ b/lib/puppet/functions/is_ipv4_address.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_ipv4_address) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_ipv4_address', "This method is deprecated, please use match expressions with Stdlib::Compat::Ipv4 instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_ipv4_address", args)
+ end
+end
diff --git a/lib/puppet/functions/is_ipv6_address.rb b/lib/puppet/functions/is_ipv6_address.rb
new file mode 100644
index 0000000..be0c98a
--- /dev/null
+++ b/lib/puppet/functions/is_ipv6_address.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_ipv6_address) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_ipv4_address', "This method is deprecated, please use match expressions with Stdlib::Compat::Ipv6 instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_ipv6_address", args)
+ end
+end
diff --git a/lib/puppet/functions/is_numeric.rb b/lib/puppet/functions/is_numeric.rb
new file mode 100644
index 0000000..f5e9d41
--- /dev/null
+++ b/lib/puppet/functions/is_numeric.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_numeric) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_numeric', "This method is deprecated, please use match expressions with Stdlib::Compat::Numeric instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_numeric", args)
+ end
+end
diff --git a/lib/puppet/functions/is_string.rb b/lib/puppet/functions/is_string.rb
new file mode 100644
index 0000000..a05a796
--- /dev/null
+++ b/lib/puppet/functions/is_string.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:is_string) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'is_string', "This method is deprecated, please use match expressions with Stdlib::Compat::String instead. They are described at https://docs.puppet.com/puppet/latest/reference/lang_data_type.html#match-expressions.")
+ scope.send("function_is_string", args)
+ end
+end
diff --git a/lib/puppet/functions/type_of.rb b/lib/puppet/functions/type_of.rb
index 02cdd4d..01f1f49 100644
--- a/lib/puppet/functions/type_of.rb
+++ b/lib/puppet/functions/type_of.rb
@@ -10,6 +10,8 @@
# See the documentation for "The Puppet Type System" for more information about types.
# See the `assert_type()` function for flexible ways to assert the type of a value.
#
+# The built-in type() function in puppet is generally preferred over this function
+# this function is provided for backwards compatibility.
Puppet::Functions.create_function(:type_of) do
def type_of(value)
Puppet::Pops::Types::TypeCalculator.infer_set(value)
diff --git a/lib/puppet/functions/validate_absolute_path.rb b/lib/puppet/functions/validate_absolute_path.rb
new file mode 100644
index 0000000..a3c696d
--- /dev/null
+++ b/lib/puppet/functions/validate_absolute_path.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_absolute_path) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_absolute_path', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Absolute_Path. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_absolute_path", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_array.rb b/lib/puppet/functions/validate_array.rb
new file mode 100644
index 0000000..f59c6b4
--- /dev/null
+++ b/lib/puppet/functions/validate_array.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_array) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_array', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Array. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_array", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_bool.rb b/lib/puppet/functions/validate_bool.rb
new file mode 100644
index 0000000..5cfb2ac
--- /dev/null
+++ b/lib/puppet/functions/validate_bool.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_bool) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_bool', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Bool. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_bool", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_hash.rb b/lib/puppet/functions/validate_hash.rb
new file mode 100644
index 0000000..89ad9ab
--- /dev/null
+++ b/lib/puppet/functions/validate_hash.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_hash) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_hash', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Hash. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_hash", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_integer.rb b/lib/puppet/functions/validate_integer.rb
new file mode 100644
index 0000000..475ea0f
--- /dev/null
+++ b/lib/puppet/functions/validate_integer.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_integer) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_integer', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Integer. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_integer", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_ip_address.rb b/lib/puppet/functions/validate_ip_address.rb
new file mode 100644
index 0000000..1521c08
--- /dev/null
+++ b/lib/puppet/functions/validate_ip_address.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_ip_address) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_ip_address', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ip_Address. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_ip_address", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_ipv4_address.rb b/lib/puppet/functions/validate_ipv4_address.rb
new file mode 100644
index 0000000..fe66ab3
--- /dev/null
+++ b/lib/puppet/functions/validate_ipv4_address.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_ipv4_address) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_ipv4_address', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ipv4_Address. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_ipv4_address", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_ipv6_address.rb b/lib/puppet/functions/validate_ipv6_address.rb
new file mode 100644
index 0000000..7cc3cbd
--- /dev/null
+++ b/lib/puppet/functions/validate_ipv6_address.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_ipv6_address) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_ipv6_address', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ipv6_address. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_ipv6_address", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_legacy.rb b/lib/puppet/functions/validate_legacy.rb
new file mode 100644
index 0000000..c9d1f56
--- /dev/null
+++ b/lib/puppet/functions/validate_legacy.rb
@@ -0,0 +1,62 @@
+Puppet::Functions.create_function(:validate_legacy) do
+ # The function checks a value against both the target_type (new) and the previous_validation function (old).
+
+ dispatch :validate_legacy do
+ param 'Any', :scope
+ param 'Type', :target_type
+ param 'String', :function_name
+ param 'Any', :value
+ repeated_param 'Any', :args
+ end
+
+ dispatch :validate_legacy_s do
+ param 'Any', :scope
+ param 'String', :type_string
+ param 'String', :function_name
+ param 'Any', :value
+ repeated_param 'Any', :args
+ end
+
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+
+ def validate_legacy_s(scope, type_string, *args)
+ t = Puppet::Pops::Types::TypeParser.new.parse(type_string, scope)
+ validate_legacy(scope, t, *args)
+ end
+
+ def validate_legacy(scope, target_type, function_name, value, *prev_args)
+ if assert_type(target_type, value)
+ if previous_validation(scope, function_name, value, *prev_args)
+ # Silently passes
+ else
+ Puppet.notice("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("validate_legacy(#{function_name})", target_type, inferred_type)
+ if previous_validation(scope, function_name, value, *prev_args)
+ call_function('deprecation', 'validate_legacy', error_msg)
+ else
+ call_function('fail', error_msg)
+ end
+ end
+ end
+
+ def previous_validation(scope, function_name, value, *prev_args)
+ # Call the previous validation function and catch any errors. Return true if no errors are thrown.
+ begin
+ scope.send("function_#{function_name}".to_s, [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/lib/puppet/functions/validate_numeric.rb b/lib/puppet/functions/validate_numeric.rb
new file mode 100644
index 0000000..3052d35
--- /dev/null
+++ b/lib/puppet/functions/validate_numeric.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_numeric) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_numeric', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Numeric. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_numeric", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_re.rb b/lib/puppet/functions/validate_re.rb
new file mode 100644
index 0000000..19443a8
--- /dev/null
+++ b/lib/puppet/functions/validate_re.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_re) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_re', "This method is deprecated, please use the stdlib validate_legacy function, with Pattern[]. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_re", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_slength.rb b/lib/puppet/functions/validate_slength.rb
new file mode 100644
index 0000000..584232a
--- /dev/null
+++ b/lib/puppet/functions/validate_slength.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_slength) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_slength', "This method is deprecated, please use the stdlib validate_legacy function, with String[]. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_slength", args)
+ end
+end
diff --git a/lib/puppet/functions/validate_string.rb b/lib/puppet/functions/validate_string.rb
new file mode 100644
index 0000000..91ff004
--- /dev/null
+++ b/lib/puppet/functions/validate_string.rb
@@ -0,0 +1,15 @@
+Puppet::Functions.create_function(:validate_string) do
+ dispatch :deprecation_gen do
+ param 'Any', :scope
+ repeated_param 'Any', :args
+ end
+ # Workaround PUP-4438 (fixed: https://github.com/puppetlabs/puppet/commit/e01c4dc924cd963ff6630008a5200fc6a2023b08#diff-c937cc584953271bb3d3b3c2cb141790R221) to support puppet < 4.1.0 and puppet < 3.8.1.
+ def call(scope, *args)
+ manipulated_args = [scope] + args
+ self.class.dispatcher.dispatch(self, scope, manipulated_args)
+ end
+ def deprecation_gen(scope, *args)
+ call_function('deprecation', 'validate_string', "This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::String. There is further documentation for validate_legacy function in the README.")
+ scope.send("function_validate_string", args)
+ end
+end
diff --git a/lib/puppet/parser/functions/any2bool.rb b/lib/puppet/parser/functions/any2bool.rb
new file mode 100644
index 0000000..f0f8f83
--- /dev/null
+++ b/lib/puppet/parser/functions/any2bool.rb
@@ -0,0 +1,55 @@
+#
+# any2bool.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:any2bool, :type => :rvalue, :doc => <<-EOS
+This converts 'anything' to a boolean. In practise it does the following:
+
+* Strings such as Y,y,1,T,t,TRUE,yes,'true' will return true
+* Strings such as 0,F,f,N,n,FALSE,no,'false' will return false
+* Booleans will just return their original value
+* Number (or a string representation of a number) > 0 will return true, otherwise false
+* undef will return false
+* Anything else will return true
+ EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "any2bool(): Wrong number of arguments " +
+ "given (#{arguments.size} for 1)") if arguments.size < 1
+
+ # If argument is already Boolean, return it
+ if !!arguments[0] == arguments[0]
+ return arguments[0]
+ end
+
+ arg = arguments[0]
+
+ if arg == nil
+ return false
+ end
+
+ if arg == :undef
+ return false
+ end
+
+ valid_float = !!Float(arg) rescue false
+
+ if arg.is_a?(Numeric)
+ return function_num2bool( [ arguments[0] ] )
+ end
+
+ if arg.is_a?(String)
+ if valid_float
+ return function_num2bool( [ arguments[0] ] )
+ else
+ return function_str2bool( [ arguments[0] ] )
+ end
+ end
+
+ return true
+
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/assert_private.rb b/lib/puppet/parser/functions/assert_private.rb
new file mode 100644
index 0000000..66c79cc
--- /dev/null
+++ b/lib/puppet/parser/functions/assert_private.rb
@@ -0,0 +1,29 @@
+#
+# assert_private.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:assert_private, :doc => <<-'EOS'
+ Sets the current class or definition as private.
+ Calling the class or definition from outside the current module will fail.
+ EOS
+ ) do |args|
+
+ raise(Puppet::ParseError, "assert_private(): Wrong number of arguments "+
+ "given (#{args.size}}) for 0 or 1)") if args.size > 1
+
+ scope = self
+ if scope.lookupvar('module_name') != scope.lookupvar('caller_module_name')
+ message = nil
+ if args[0] and args[0].is_a? String
+ message = args[0]
+ else
+ manifest_name = scope.source.name
+ manifest_type = scope.source.type
+ message = (manifest_type.to_s == 'hostclass') ? 'Class' : 'Definition'
+ message += " #{manifest_name} is private"
+ end
+ raise(Puppet::ParseError, message)
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/base64.rb b/lib/puppet/parser/functions/base64.rb
index 617ba31..a8998f2 100644
--- a/lib/puppet/parser/functions/base64.rb
+++ b/lib/puppet/parser/functions/base64.rb
@@ -6,14 +6,19 @@ module Puppet::Parser::Functions
Usage:
- $encodestring = base64('encode','thestring')
- $decodestring = base64('decode','dGhlc3RyaW5n')
+ $encodestring = base64('encode', 'thestring')
+ $decodestring = base64('decode', 'dGhlc3RyaW5n')
+
+ # explicitly define encode/decode method: default, strict, urlsafe
+ $method = 'default'
+ $encodestring = base64('encode', 'thestring', $method)
+ $decodestring = base64('decode', 'dGhlc3RyaW5n', $method)
ENDHEREDOC
require 'base64'
- raise Puppet::ParseError, ("base64(): Wrong number of arguments (#{args.length}; must be = 2)") unless args.length == 2
+ raise Puppet::ParseError, ("base64(): Wrong number of arguments (#{args.length}; must be >= 2)") unless args.length >= 2
actions = ['encode','decode']
@@ -25,11 +30,37 @@ module Puppet::Parser::Functions
raise Puppet::ParseError, ("base64(): the second argument must be a string to base64")
end
+ method = ['default','strict','urlsafe']
+
+ if args.length <= 2
+ chosenMethod = 'default'
+ else
+ chosenMethod = args[2]
+ end
+
+ unless method.include?(chosenMethod)
+ raise Puppet::ParseError, ("base64(): the third argument must be one of 'default', 'strict', or 'urlsafe'")
+ end
+
case args[0]
when 'encode'
- result = Base64.encode64(args[1])
+ case chosenMethod
+ when 'default'
+ result = Base64.encode64(args[1])
+ when 'strict'
+ result = Base64.strict_encode64(args[1])
+ when 'urlsafe'
+ result = Base64.urlsafe_encode64(args[1])
+ end
when 'decode'
- result = Base64.decode64(args[1])
+ case chosenMethod
+ when 'default'
+ result = Base64.decode64(args[1])
+ when 'strict'
+ result = Base64.strict_decode64(args[1])
+ when 'urlsafe'
+ result = Base64.urlsafe_decode64(args[1])
+ end
end
return result
diff --git a/lib/puppet/parser/functions/bool2str.rb b/lib/puppet/parser/functions/bool2str.rb
index fcd3791..7e36474 100644
--- a/lib/puppet/parser/functions/bool2str.rb
+++ b/lib/puppet/parser/functions/bool2str.rb
@@ -4,15 +4,29 @@
module Puppet::Parser::Functions
newfunction(:bool2str, :type => :rvalue, :doc => <<-EOS
- Converts a boolean to a string.
+ Converts a boolean to a string using optionally supplied arguments. The
+ optional second and third arguments represent what true and false will be
+ converted to respectively. If only one argument is given, it will be
+ converted from a boolean to a string containing 'true' or 'false'.
+
+ *Examples:*
+
+ bool2str(true) => 'true'
+ bool2str(true, 'yes', 'no') => 'yes'
+ bool2str(false, 't', 'f') => 'f'
+
Requires a single boolean as an input.
EOS
) do |arguments|
- raise(Puppet::ParseError, "bool2str(): Wrong number of arguments " +
- "given (#{arguments.size} for 1)") if arguments.size < 1
+ unless arguments.size == 1 or arguments.size == 3
+ raise(Puppet::ParseError, "bool2str(): Wrong number of arguments " +
+ "given (#{arguments.size} for 3)")
+ end
value = arguments[0]
+ true_string = arguments[1] || 'true'
+ false_string = arguments[2] || 'false'
klass = value.class
# We can have either true or false, and nothing else
@@ -20,7 +34,11 @@ module Puppet::Parser::Functions
raise(Puppet::ParseError, 'bool2str(): Requires a boolean to work with')
end
- return value.to_s
+ unless [true_string, false_string].all?{|x| x.kind_of?(String)}
+ raise(Puppet::ParseError, "bool2str(): Requires strings to convert to" )
+ end
+
+ return value ? true_string : false_string
end
end
diff --git a/lib/puppet/parser/functions/ceiling.rb b/lib/puppet/parser/functions/ceiling.rb
new file mode 100644
index 0000000..5f3b10b
--- /dev/null
+++ b/lib/puppet/parser/functions/ceiling.rb
@@ -0,0 +1,25 @@
+module Puppet::Parser::Functions
+ newfunction(:ceiling, :type => :rvalue, :doc => <<-EOS
+ Returns the smallest integer greater or equal to the argument.
+ Takes a single numeric value as an argument.
+ EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "ceiling(): Wrong number of arguments " +
+ "given (#{arguments.size} for 1)") if arguments.size != 1
+
+ begin
+ arg = Float(arguments[0])
+ rescue TypeError, ArgumentError => e
+ raise(Puppet::ParseError, "ceiling(): Wrong argument type " +
+ "given (#{arguments[0]} for Numeric)")
+ end
+
+ raise(Puppet::ParseError, "ceiling(): Wrong argument type " +
+ "given (#{arg.class} for Numeric)") if arg.is_a?(Numeric) == false
+
+ arg.ceil
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/clamp.rb b/lib/puppet/parser/functions/clamp.rb
new file mode 100644
index 0000000..432c7c1
--- /dev/null
+++ b/lib/puppet/parser/functions/clamp.rb
@@ -0,0 +1,30 @@
+#
+# clamp.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:clamp, :type => :rvalue, :arity => -2, :doc => <<-EOS
+ Clamps value to a range.
+ EOS
+ ) do |args|
+
+ args.flatten!
+
+ raise(Puppet::ParseError, 'clamp(): Wrong number of arguments, ' +
+ 'need three to clamp') if args.size != 3
+
+ # check values out
+ args.each do |value|
+ case [value.class]
+ when [String]
+ raise(Puppet::ParseError, "clamp(): Required explicit numeric (#{value}:String)") unless value =~ /^\d+$/
+ when [Hash]
+ raise(Puppet::ParseError, "clamp(): The Hash type is not allowed (#{value})")
+ end
+ end
+
+ # convert to numeric each element
+ # then sort them and get a middle value
+ args.map{ |n| n.to_i }.sort[1]
+ end
+end
diff --git a/lib/puppet/parser/functions/concat.rb b/lib/puppet/parser/functions/concat.rb
index 618e62d..91edb4e 100644
--- a/lib/puppet/parser/functions/concat.rb
+++ b/lib/puppet/parser/functions/concat.rb
@@ -31,7 +31,7 @@ Would result in:
arguments.shift
arguments.each do |x|
- result = result + Array(x)
+ result = result + (x.is_a?(Array) ? x : [x])
end
return result
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/defined_with_params.rb b/lib/puppet/parser/functions/defined_with_params.rb
index d7df306..99687ae 100644
--- a/lib/puppet/parser/functions/defined_with_params.rb
+++ b/lib/puppet/parser/functions/defined_with_params.rb
@@ -26,7 +26,10 @@ ENDOFDOC
ret = false
if resource = findresource(reference.to_s)
matches = params.collect do |key, value|
- resource[key] == value
+ # eql? avoids bugs caused by monkeypatching in puppet
+ resource_is_undef = resource[key].eql?(:undef) || resource[key].nil?
+ value_is_undef = value.eql?(:undef) || value.nil?
+ (resource_is_undef && value_is_undef) || (resource[key] == value)
end
ret = params.empty? || !matches.include?(false)
end
diff --git a/lib/puppet/parser/functions/delete.rb b/lib/puppet/parser/functions/delete.rb
index f548b44..466c55c 100644
--- a/lib/puppet/parser/functions/delete.rb
+++ b/lib/puppet/parser/functions/delete.rb
@@ -2,8 +2,6 @@
# delete.rb
#
-# TODO(Krzysztof Wilczynski): We need to add support for regular expression ...
-
module Puppet::Parser::Functions
newfunction(:delete, :type => :rvalue, :doc => <<-EOS
Deletes all instances of a given element from an array, substring from a
@@ -25,10 +23,8 @@ string, or key from a hash.
EOS
) do |arguments|
- if (arguments.size != 2) then
- raise(Puppet::ParseError, "delete(): Wrong number of arguments "+
- "given #{arguments.size} for 2.")
- end
+ raise(Puppet::ParseError, "delete(): Wrong number of arguments "+
+ "given #{arguments.size} for 2") unless arguments.size == 2
collection = arguments[0].dup
Array(arguments[1]).each do |item|
diff --git a/lib/puppet/parser/functions/delete_regex.rb b/lib/puppet/parser/functions/delete_regex.rb
new file mode 100644
index 0000000..d72b3e9
--- /dev/null
+++ b/lib/puppet/parser/functions/delete_regex.rb
@@ -0,0 +1,45 @@
+#
+# delete_regex.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:delete_regex, :type => :rvalue, :doc => <<-EOS
+deletes all instances of a given element that match a regular expression
+from an array or key from a hash. Multiple regular expressions are assumed
+to be matched as an OR.
+
+*Examples:*
+
+ delete_regex(['a','b','c','b'], 'b')
+ Would return: ['a','c']
+
+ delete_regex(['a','b','c','b'], ['b', 'c'])
+ Would return: ['a']
+
+ delete_regex({'a'=>1,'b'=>2,'c'=>3}, 'b')
+ Would return: {'a'=>1,'c'=>3}
+
+ delete_regex({'a'=>1,'b'=>2,'c'=>3}, '^a$')
+ Would return: {'b'=>2,'c'=>3}
+
+ EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "delete_regex(): Wrong number of arguments "+
+ "given #{arguments.size} for 2") unless arguments.size == 2
+
+ collection = arguments[0].dup
+ Array(arguments[1]).each do |item|
+ case collection
+ when Array, Hash, String
+ collection.reject! { |coll_item| (coll_item =~ %r{\b#{item}\b}) }
+ else
+ raise(TypeError, "delete_regex(): First argument must be an Array, " +
+ "Hash, or String. Given an argument of class #{collection.class}.")
+ end
+ end
+ collection
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/deprecation.rb b/lib/puppet/parser/functions/deprecation.rb
new file mode 100644
index 0000000..cd64fe2
--- /dev/null
+++ b/lib/puppet/parser/functions/deprecation.rb
@@ -0,0 +1,17 @@
+module Puppet::Parser::Functions
+ newfunction(:deprecation, :doc => <<-EOS
+ Function to print deprecation warnings (this is the 3.X version of it), The uniqueness key - can appear once. The msg is the message text including any positional information that is formatted by the user/caller of the method.).
+EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "deprecation: Wrong number of arguments " +
+ "given (#{arguments.size} for 2)") unless arguments.size == 2
+
+ key = arguments[0]
+ message = arguments[1]
+
+ if ENV['STDLIB_LOG_DEPRECATIONS'] == "true"
+ warning("deprecation. #{key}. #{message}")
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/dig.rb b/lib/puppet/parser/functions/dig.rb
new file mode 100644
index 0000000..34fa701
--- /dev/null
+++ b/lib/puppet/parser/functions/dig.rb
@@ -0,0 +1,16 @@
+#
+# dig.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:dig, :type => :rvalue, :doc => <<-EOS
+ DEPRECATED: This function has been replaced in Puppet 4.5.0, please use dig44() for backwards compatibility or use the new version.
+ EOS
+ ) do |arguments|
+ warning("dig() DEPRECATED: This function has been replaced in Puppet 4.5.0, please use dig44() for backwards compatibility or use the new version.")
+ if ! Puppet::Parser::Functions.autoloader.loaded?(:dig44)
+ Puppet::Parser::Functions.autoloader.load(:dig44)
+ end
+ function_dig44(arguments)
+ end
+end
diff --git a/lib/puppet/parser/functions/dig44.rb b/lib/puppet/parser/functions/dig44.rb
new file mode 100644
index 0000000..1e7c318
--- /dev/null
+++ b/lib/puppet/parser/functions/dig44.rb
@@ -0,0 +1,73 @@
+#
+# dig44.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(
+ :dig44,
+ :type => :rvalue,
+ :arity => -2,
+ :doc => <<-eos
+DEPRECATED: This function has been replaced in puppet 4.5.0.
+
+Looks up into a complex structure of arrays and hashes and returns a value
+or the default value if nothing was found.
+
+Key can contain slashes to describe path components. The function will go down
+the structure and try to extract the required value.
+
+$data = {
+ 'a' => {
+ 'b' => [
+ 'b1',
+ 'b2',
+ 'b3',
+ ]
+ }
+}
+
+$value = dig44($data, ['a', 'b', '2'], 'not_found')
+=> $value = 'b3'
+
+a -> first hash key
+b -> second hash key
+2 -> array index starting with 0
+
+not_found -> (optional) will be returned if there is no value or the path
+did not match. Defaults to nil.
+
+In addition to the required "key" argument, the function accepts a default
+argument. It will be returned if no value was found or a path component is
+missing. And the fourth argument can set a variable path separator.
+ eos
+ ) do |arguments|
+ # Two arguments are required
+ raise(Puppet::ParseError, "dig44(): Wrong number of arguments " +
+ "given (#{arguments.size} for at least 2)") if arguments.size < 2
+
+ data, path, default = *arguments
+
+ unless data.is_a?(Hash) or data.is_a?(Array)
+ raise(Puppet::ParseError, "dig44(): first argument must be a hash or an array, " <<
+ "given #{data.class.name}")
+ end
+
+ unless path.is_a? Array
+ raise(Puppet::ParseError, "dig44(): second argument must be an array, " <<
+ "given #{path.class.name}")
+ end
+
+ value = path.reduce(data) do |structure, key|
+ if structure.is_a? Hash or structure.is_a? Array
+ if structure.is_a? Array
+ key = Integer key rescue break
+ end
+ break if structure[key].nil? or structure[key] == :undef
+ structure[key]
+ else
+ break
+ end
+ end
+ value.nil? ? default : value
+ end
+end
diff --git a/lib/puppet/parser/functions/dirname.rb b/lib/puppet/parser/functions/dirname.rb
index ea8cc1e..40b300d 100644
--- a/lib/puppet/parser/functions/dirname.rb
+++ b/lib/puppet/parser/functions/dirname.rb
@@ -4,11 +4,17 @@ module Puppet::Parser::Functions
EOS
) do |arguments|
- raise(Puppet::ParseError, "dirname(): Wrong number of arguments " +
- "given (#{arguments.size} for 1)") if arguments.size < 1
+ if arguments.size < 1 then
+ raise(Puppet::ParseError, "dirname(): No arguments given")
+ end
+ if arguments.size > 1 then
+ raise(Puppet::ParseError, "dirname(): Too many arguments given (#{arguments.size})")
+ end
+ unless arguments[0].is_a?(String)
+ raise(Puppet::ParseError, 'dirname(): Requires string as argument')
+ end
- path = arguments[0]
- return File.dirname(path)
+ return File.dirname(arguments[0])
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/empty.rb b/lib/puppet/parser/functions/empty.rb
index cca620f..b5a3cde 100644
--- a/lib/puppet/parser/functions/empty.rb
+++ b/lib/puppet/parser/functions/empty.rb
@@ -13,14 +13,18 @@ Returns true if the variable is empty.
value = arguments[0]
- unless value.is_a?(Array) || value.is_a?(Hash) || value.is_a?(String)
+ unless value.is_a?(Array) || value.is_a?(Hash) || value.is_a?(String) || value.is_a?(Numeric)
raise(Puppet::ParseError, 'empty(): Requires either ' +
- 'array, hash or string to work with')
+ 'array, hash, string or integer to work with')
end
- result = value.empty?
+ if value.is_a?(Numeric)
+ return false
+ else
+ result = value.empty?
- return result
+ return result
+ end
end
end
diff --git a/lib/puppet/parser/functions/enclose_ipv6.rb b/lib/puppet/parser/functions/enclose_ipv6.rb
new file mode 100644
index 0000000..80ffc3a
--- /dev/null
+++ b/lib/puppet/parser/functions/enclose_ipv6.rb
@@ -0,0 +1,45 @@
+#
+# enclose_ipv6.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:enclose_ipv6, :type => :rvalue, :doc => <<-EOS
+Takes an array of ip addresses and encloses the ipv6 addresses with square brackets.
+ EOS
+ ) do |arguments|
+
+ require 'ipaddr'
+
+ rescuable_exceptions = [ ArgumentError ]
+ if defined?(IPAddr::InvalidAddressError)
+ rescuable_exceptions << IPAddr::InvalidAddressError
+ end
+
+ if (arguments.size != 1) then
+ raise(Puppet::ParseError, "enclose_ipv6(): Wrong number of arguments "+
+ "given #{arguments.size} for 1")
+ end
+ unless arguments[0].is_a?(String) or arguments[0].is_a?(Array) then
+ raise(Puppet::ParseError, "enclose_ipv6(): Wrong argument type "+
+ "given #{arguments[0].class} expected String or Array")
+ end
+
+ input = [arguments[0]].flatten.compact
+ result = []
+
+ input.each do |val|
+ unless val == '*'
+ begin
+ ip = IPAddr.new(val)
+ rescue *rescuable_exceptions
+ raise(Puppet::ParseError, "enclose_ipv6(): Wrong argument "+
+ "given #{val} is not an ip address.")
+ end
+ val = "[#{ip.to_s}]" if ip.ipv6?
+ end
+ result << val
+ end
+
+ return result.uniq
+ end
+end
diff --git a/lib/puppet/parser/functions/ensure_packages.rb b/lib/puppet/parser/functions/ensure_packages.rb
index f1da4aa..439af1e 100644
--- a/lib/puppet/parser/functions/ensure_packages.rb
+++ b/lib/puppet/parser/functions/ensure_packages.rb
@@ -17,18 +17,29 @@ third argument to the ensure_resource() function.
raise(Puppet::ParseError, 'ensure_packages(): Requires second argument to be a Hash')
end
- packages = Array(arguments[0])
+ if arguments[0].is_a?(Hash)
+ if arguments[1]
+ defaults = { 'ensure' => 'present' }.merge(arguments[1])
+ else
+ defaults = { 'ensure' => 'present' }
+ end
- if arguments[1]
- defaults = { 'ensure' => 'present' }.merge(arguments[1])
+ Puppet::Parser::Functions.function(:ensure_resources)
+ function_ensure_resources(['package', arguments[0].dup, defaults ])
else
- defaults = { 'ensure' => 'present' }
- end
+ packages = Array(arguments[0])
+
+ if arguments[1]
+ defaults = { 'ensure' => 'present' }.merge(arguments[1])
+ else
+ defaults = { 'ensure' => 'present' }
+ end
- Puppet::Parser::Functions.function(:ensure_resource)
- packages.each { |package_name|
- function_ensure_resource(['package', package_name, defaults ])
+ Puppet::Parser::Functions.function(:ensure_resource)
+ packages.each { |package_name|
+ function_ensure_resource(['package', package_name, defaults ])
}
+ end
end
end
diff --git a/lib/puppet/parser/functions/ensure_resources.rb b/lib/puppet/parser/functions/ensure_resources.rb
new file mode 100644
index 0000000..b3c51e6
--- /dev/null
+++ b/lib/puppet/parser/functions/ensure_resources.rb
@@ -0,0 +1,54 @@
+require 'puppet/parser/functions'
+
+Puppet::Parser::Functions.newfunction(:ensure_resources,
+ :type => :statement,
+ :doc => <<-'ENDOFDOC'
+Takes a resource type, title (only hash), and a list of attributes that describe a
+resource.
+
+ user { 'dan':
+ gid => 'mygroup',
+ ensure => present,
+ }
+
+An hash of resources should be passed in and each will be created with
+the type and parameters specified if it doesn't already exist.
+
+ ensure_resources('user', {'dan' => { gid => 'mygroup', uid => '600' } , 'alex' => { gid => 'mygroup' }}, {'ensure' => 'present'})
+
+From Hiera Backend:
+
+userlist:
+ dan:
+ gid: 'mygroup'
+ uid: '600'
+ alex:
+ gid: 'mygroup'
+
+Call:
+ensure_resources('user', hiera_hash('userlist'), {'ensure' => 'present'})
+
+ENDOFDOC
+) do |vals|
+ type, title, params = vals
+ raise(ArgumentError, 'Must specify a type') unless type
+ raise(ArgumentError, 'Must specify a title') unless title
+ params ||= {}
+
+ if title.is_a?(Hash)
+ resource_hash = title.dup
+ resources = resource_hash.keys
+
+ Puppet::Parser::Functions.function(:ensure_resource)
+ resources.each { |resource_name|
+ if resource_hash[resource_name]
+ params_merged = params.merge(resource_hash[resource_name])
+ else
+ params_merged = params
+ end
+ function_ensure_resource([ type, resource_name, params_merged ])
+ }
+ else
+ raise(Puppet::ParseError, 'ensure_resources(): Requires second argument to be a Hash')
+ end
+end
diff --git a/lib/puppet/parser/functions/fqdn_rand_string.rb b/lib/puppet/parser/functions/fqdn_rand_string.rb
new file mode 100644
index 0000000..2bb1287
--- /dev/null
+++ b/lib/puppet/parser/functions/fqdn_rand_string.rb
@@ -0,0 +1,34 @@
+Puppet::Parser::Functions::newfunction(
+ :fqdn_rand_string,
+ :arity => -2,
+ :type => :rvalue,
+ :doc => "Usage: `fqdn_rand_string(LENGTH, [CHARSET], [SEED])`. LENGTH is
+ required and must be a positive integer. CHARSET is optional and may be
+ `undef` or a string. SEED is optional and may be any number or string.
+
+ Generates a random string LENGTH characters long using the character set
+ provided by CHARSET, combining the `$fqdn` fact and the value of SEED for
+ repeatable randomness. (That is, each node will get a different random
+ string from this function, but a given node's result will be the same every
+ time unless its hostname changes.) Adding a SEED can be useful if you need
+ more than one unrelated string. CHARSET will default to alphanumeric if
+ `undef` or an empty string.") do |args|
+ raise(ArgumentError, "fqdn_rand_string(): wrong number of arguments (0 for 1)") if args.size == 0
+ Puppet::Parser::Functions.function('is_integer')
+ raise(ArgumentError, "fqdn_rand_string(): first argument must be a positive integer") unless function_is_integer([args[0]]) and args[0].to_i > 0
+ raise(ArgumentError, "fqdn_rand_string(): second argument must be undef or a string") unless args[1].nil? or args[1].is_a? String
+
+ Puppet::Parser::Functions.function('fqdn_rand')
+
+ length = args.shift.to_i
+ charset = args.shift.to_s.chars.to_a
+
+ charset = (0..9).map { |i| i.to_s } + ('A'..'Z').to_a + ('a'..'z').to_a if charset.empty?
+
+ rand_string = ''
+ for current in 1..length
+ rand_string << charset[function_fqdn_rand([charset.size, (args + [current.to_s]).join(':')]).to_i]
+ end
+
+ rand_string
+end
diff --git a/lib/puppet/parser/functions/fqdn_rotate.rb b/lib/puppet/parser/functions/fqdn_rotate.rb
index 7f4d37d..b66431d 100644
--- a/lib/puppet/parser/functions/fqdn_rotate.rb
+++ b/lib/puppet/parser/functions/fqdn_rotate.rb
@@ -2,16 +2,23 @@
# fqdn_rotate.rb
#
-module Puppet::Parser::Functions
- newfunction(:fqdn_rotate, :type => :rvalue, :doc => <<-EOS
-Rotates an array a random number of times based on a nodes fqdn.
- EOS
- ) do |arguments|
+Puppet::Parser::Functions.newfunction(
+ :fqdn_rotate,
+ :type => :rvalue,
+ :doc => "Usage: `fqdn_rotate(VALUE, [SEED])`. VALUE is required and
+ must be an array or a string. SEED is optional and may be any number
+ or string.
+
+ Rotates VALUE a random number of times, combining the `$fqdn` fact and
+ the value of SEED for repeatable randomness. (That is, each node will
+ get a different random rotation from this function, but a given node's
+ result will be the same every time unless its hostname changes.) Adding
+ a SEED can be useful if you need more than one unrelated rotation.") do |args|
raise(Puppet::ParseError, "fqdn_rotate(): Wrong number of arguments " +
- "given (#{arguments.size} for 1)") if arguments.size < 1
+ "given (#{args.size} for 1)") if args.size < 1
- value = arguments[0]
+ value = args.shift
require 'digest/md5'
unless value.is_a?(Array) || value.is_a?(String)
@@ -31,15 +38,26 @@ Rotates an array a random number of times based on a nodes fqdn.
elements = result.size
- srand(Digest::MD5.hexdigest([lookupvar('::fqdn'),arguments].join(':')).hex)
- rand(elements).times {
+ seed = Digest::MD5.hexdigest([lookupvar('::fqdn'),args].join(':')).hex
+ # deterministic_rand() was added in Puppet 3.2.0; reimplement if necessary
+ if Puppet::Util.respond_to?(:deterministic_rand)
+ offset = Puppet::Util.deterministic_rand(seed, elements).to_i
+ else
+ if defined?(Random) == 'constant' && Random.class == Class
+ offset = Random.new(seed).rand(elements)
+ else
+ old_seed = srand(seed)
+ offset = rand(elements)
+ srand(old_seed)
+ end
+ end
+ offset.times {
result.push result.shift
}
result = string ? result.join : result
return result
- end
end
# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/fqdn_uuid.rb b/lib/puppet/parser/functions/fqdn_uuid.rb
new file mode 100644
index 0000000..30205d0
--- /dev/null
+++ b/lib/puppet/parser/functions/fqdn_uuid.rb
@@ -0,0 +1,92 @@
+require 'digest/sha1'
+
+module Puppet::Parser::Functions
+ newfunction(:fqdn_uuid, :type => :rvalue, :doc => <<-END) do |args|
+
+ Creates a UUID based on a given string, assumed to be the FQDN
+
+ For example, to generate a UUID based on the FQDN of a system:
+
+ Usage:
+
+ $uuid = fqdn_uuid($::fqdn)
+
+ The generated UUID will be the same for the given hostname
+
+ The resulting UUID is returned on the form:
+
+ 1d839dea-5e10-5243-88eb-e66815bd7d5c
+
+ (u.e. without any curly braces.)
+
+ The generated UUID is a version 5 UUID with the V5 DNS namespace:
+
+ 6ba7b810-9dad-11d1-80b4-00c04fd430c8
+
+ This only supports a the V5 SHA-1 hash, using the DNS namespace.
+
+ Please consult http://www.ietf.org/rfc/rfc4122.txt for the details on
+ UUID generation and example implementation.
+
+ No verification is present at the moment as whether the domain name given
+ is in fact a correct fully-qualified domain name. Therefore any arbitrary
+ string and/or alpha-numeric value can subside for a domain name.
+ EOS
+
+ END
+
+ if args.length == 0
+ raise(ArgumentError, "fqdn_uuid: No arguments given")
+ elsif args.length == 1
+ fqdn = args[0]
+ else
+ raise(ArgumentError, "fqdn_uuid: Too many arguments given (#{args.length})")
+ end
+
+ # Code lovingly taken from
+ # https://github.com/puppetlabs/marionette-collective/blob/master/lib/mcollective/ssl.rb
+
+ # This is the UUID version 5 type DNS name space which is as follows:
+ #
+ # 6ba7b810-9dad-11d1-80b4-00c04fd430c8
+ #
+ uuid_name_space_dns = [0x6b,
+ 0xa7,
+ 0xb8,
+ 0x10,
+ 0x9d,
+ 0xad,
+ 0x11,
+ 0xd1,
+ 0x80,
+ 0xb4,
+ 0x00,
+ 0xc0,
+ 0x4f,
+ 0xd4,
+ 0x30,
+ 0xc8
+ ].map {|b| b.chr}.join
+
+ sha1 = Digest::SHA1.new
+ sha1.update(uuid_name_space_dns)
+ sha1.update(fqdn)
+
+ # first 16 bytes..
+ bytes = sha1.digest[0, 16].bytes.to_a
+
+ # version 5 adjustments
+ bytes[6] &= 0x0f
+ bytes[6] |= 0x50
+
+ # variant is DCE 1.1
+ bytes[8] &= 0x3f
+ bytes[8] |= 0x80
+
+ bytes = [4, 2, 2, 2, 6].collect do |i|
+ bytes.slice!(0, i).pack('C*').unpack('H*')
+ end
+
+ bytes.join('-')
+ end
+end
diff --git a/lib/puppet/parser/functions/getparam.rb b/lib/puppet/parser/functions/getparam.rb
index 6d51006..0a5cbe0 100644
--- a/lib/puppet/parser/functions/getparam.rb
+++ b/lib/puppet/parser/functions/getparam.rb
@@ -28,7 +28,7 @@ ENDOFDOC
return '' if param.empty?
if resource = findresource(reference.to_s)
- return resource[param] if resource[param]
+ return resource[param] unless resource[param].nil?
end
return ''
diff --git a/lib/puppet/parser/functions/getvar.rb b/lib/puppet/parser/functions/getvar.rb
index fb336b6..3af8d48 100644
--- a/lib/puppet/parser/functions/getvar.rb
+++ b/lib/puppet/parser/functions/getvar.rb
@@ -20,7 +20,13 @@ module Puppet::Parser::Functions
end
begin
- self.lookupvar("#{args[0]}")
+ result = nil
+ catch(:undefined_variable) do
+ result = self.lookupvar("#{args[0]}")
+ end
+
+ # avoid relying on incosistent behaviour around ruby return values from catch
+ result
rescue Puppet::ParseError # Eat the exception if strict_variables = true is set
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/hash.rb b/lib/puppet/parser/functions/hash.rb
index 8cc4823..89d0e07 100644
--- a/lib/puppet/parser/functions/hash.rb
+++ b/lib/puppet/parser/functions/hash.rb
@@ -29,7 +29,7 @@ Would return: {'a'=>1,'b'=>2,'c'=>3}
# This is to make it compatible with older version of Ruby ...
array = array.flatten
result = Hash[*array]
- rescue Exception
+ rescue StandardError
raise(Puppet::ParseError, 'hash(): Unable to compute ' +
'hash from array given')
end
diff --git a/lib/puppet/parser/functions/intersection.rb b/lib/puppet/parser/functions/intersection.rb
index 48f02e9..bfbb4ba 100644
--- a/lib/puppet/parser/functions/intersection.rb
+++ b/lib/puppet/parser/functions/intersection.rb
@@ -4,13 +4,13 @@
module Puppet::Parser::Functions
newfunction(:intersection, :type => :rvalue, :doc => <<-EOS
-This function returns an array an intersection of two.
+This function returns an array of the intersection of two.
*Examples:*
- intersection(["a","b","c"],["b","c","d"])
+ intersection(["a","b","c"],["b","c","d"]) # returns ["b","c"]
+ intersection(["a","b","c"],[1,2,3,4]) # returns [] (true, when evaluated as a Boolean)
-Would return: ["b","c"]
EOS
) do |arguments|
diff --git a/lib/puppet/parser/functions/is_absolute_path.rb b/lib/puppet/parser/functions/is_absolute_path.rb
new file mode 100644
index 0000000..e64777f
--- /dev/null
+++ b/lib/puppet/parser/functions/is_absolute_path.rb
@@ -0,0 +1,50 @@
+module Puppet::Parser::Functions
+ newfunction(:is_absolute_path, :type => :rvalue, :arity => 1, :doc => <<-'ENDHEREDOC') do |args|
+ Returns boolean true if the string represents an absolute path in the filesystem. This function works
+ for windows and unix style paths.
+
+ The following values will return true:
+
+ $my_path = 'C:/Program Files (x86)/Puppet Labs/Puppet'
+ is_absolute_path($my_path)
+ $my_path2 = '/var/lib/puppet'
+ is_absolute_path($my_path2)
+ $my_path3 = ['C:/Program Files (x86)/Puppet Labs/Puppet']
+ is_absolute_path($my_path3)
+ $my_path4 = ['/var/lib/puppet']
+ is_absolute_path($my_path4)
+
+ The following values will return false:
+
+ is_absolute_path(true)
+ is_absolute_path('../var/lib/puppet')
+ is_absolute_path('var/lib/puppet')
+ $undefined = undef
+ is_absolute_path($undefined)
+
+ ENDHEREDOC
+ function_deprecation([:is_absolute_path, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Absolute_path. There is further documentation for validate_legacy function in the README.'])
+ require 'puppet/util'
+
+ path = args[0]
+ # This logic was borrowed from
+ # [lib/puppet/file_serving/base.rb](https://github.com/puppetlabs/puppet/blob/master/lib/puppet/file_serving/base.rb)
+ # Puppet 2.7 and beyond will have Puppet::Util.absolute_path? Fall back to a back-ported implementation otherwise.
+ if Puppet::Util.respond_to?(:absolute_path?) then
+ value = (Puppet::Util.absolute_path?(path, :posix) or Puppet::Util.absolute_path?(path, :windows))
+ else
+ # This code back-ported from 2.7.x's lib/puppet/util.rb Puppet::Util.absolute_path?
+ # Determine in a platform-specific way whether a path is absolute. This
+ # defaults to the local platform if none is specified.
+ # Escape once for the string literal, and once for the regex.
+ slash = '[\\\\/]'
+ name = '[^\\\\/]+'
+ regexes = {
+ :windows => %r!^(([A-Z]:#{slash})|(#{slash}#{slash}#{name}#{slash}#{name})|(#{slash}#{slash}\?#{slash}#{name}))!i,
+ :posix => %r!^/!
+ }
+ value = (!!(path =~ regexes[:posix])) || (!!(path =~ regexes[:windows]))
+ end
+ value
+ end
+end
diff --git a/lib/puppet/parser/functions/is_array.rb b/lib/puppet/parser/functions/is_array.rb
index b39e184..1d2c0fa 100644
--- a/lib/puppet/parser/functions/is_array.rb
+++ b/lib/puppet/parser/functions/is_array.rb
@@ -8,6 +8,8 @@ Returns true if the variable passed to this function is an array.
EOS
) do |arguments|
+ function_deprecation([:is_array, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Array. There is further documentation for validate_legacy function in the README.'])
+
raise(Puppet::ParseError, "is_array(): Wrong number of arguments " +
"given (#{arguments.size} for 1)") if arguments.size < 1
@@ -18,5 +20,3 @@ Returns true if the variable passed to this function is an array.
return result
end
end
-
-# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/is_bool.rb b/lib/puppet/parser/functions/is_bool.rb
index 8bbdbc8..83d2ebe 100644
--- a/lib/puppet/parser/functions/is_bool.rb
+++ b/lib/puppet/parser/functions/is_bool.rb
@@ -8,6 +8,8 @@ Returns true if the variable passed to this function is a boolean.
EOS
) do |arguments|
+ function_deprecation([:is_bool, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Bool. There is further documentation for validate_legacy function in the README.'])
+
raise(Puppet::ParseError, "is_bool(): Wrong number of arguments " +
"given (#{arguments.size} for 1)") if arguments.size != 1
@@ -18,5 +20,3 @@ Returns true if the variable passed to this function is a boolean.
return result
end
end
-
-# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/is_domain_name.rb b/lib/puppet/parser/functions/is_domain_name.rb
index b3fee96..90ede32 100644
--- a/lib/puppet/parser/functions/is_domain_name.rb
+++ b/lib/puppet/parser/functions/is_domain_name.rb
@@ -13,16 +13,16 @@ Returns true if the string passed to this function is a syntactically correct do
"given #{arguments.size} for 1")
end
- domain = arguments[0]
+ # Only allow string types
+ return false unless arguments[0].is_a?(String)
+
+ domain = arguments[0].dup
# Limits (rfc1035, 3.1)
domain_max_length=255
label_min_length=1
label_max_length=63
- # Only allow string types
- return false unless domain.is_a?(String)
-
# Allow ".", it is the top level domain
return true if domain == '.'
@@ -33,6 +33,10 @@ Returns true if the string passed to this function is a syntactically correct do
return false if domain.empty?
return false if domain.length > domain_max_length
+ # The top level domain must be alphabetic if there are multiple labels.
+ # See rfc1123, 2.1
+ return false if domain.include? '.' and not /\.[A-Za-z]+$/.match(domain)
+
# Check each label in the domain
labels = domain.split('.')
vlabels = labels.each do |label|
diff --git a/lib/puppet/parser/functions/is_email_address.rb b/lib/puppet/parser/functions/is_email_address.rb
new file mode 100644
index 0000000..4fb0229
--- /dev/null
+++ b/lib/puppet/parser/functions/is_email_address.rb
@@ -0,0 +1,21 @@
+#
+# is_email_address.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:is_email_address, :type => :rvalue, :doc => <<-EOS
+Returns true if the string passed to this function is a valid email address.
+ EOS
+ ) do |arguments|
+ if arguments.size != 1
+ raise(Puppet::ParseError, 'is_email_address(): Wrong number of arguments '\
+ "given #{arguments.size} for 1")
+ end
+
+ # Taken from http://emailregex.com/ (simpler regex)
+ valid_email_regex = %r{\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z}
+ return (arguments[0] =~ valid_email_regex) == 0
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/is_float.rb b/lib/puppet/parser/functions/is_float.rb
index a2da943..1186458 100644
--- a/lib/puppet/parser/functions/is_float.rb
+++ b/lib/puppet/parser/functions/is_float.rb
@@ -8,6 +8,8 @@ Returns true if the variable passed to this function is a float.
EOS
) do |arguments|
+ function_deprecation([:is_float, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Float. There is further documentation for validate_legacy function in the README.'])
+
if (arguments.size != 1) then
raise(Puppet::ParseError, "is_float(): Wrong number of arguments "+
"given #{arguments.size} for 1")
diff --git a/lib/puppet/parser/functions/is_integer.rb b/lib/puppet/parser/functions/is_integer.rb
index c03d28d..e04fd1f 100644
--- a/lib/puppet/parser/functions/is_integer.rb
+++ b/lib/puppet/parser/functions/is_integer.rb
@@ -13,6 +13,8 @@ If given any other argument `false` is returned.
EOS
) do |arguments|
+ function_deprecation([:is_integer, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Integer. There is further documentation for validate_legacy function in the README.'])
+
if (arguments.size != 1) then
raise(Puppet::ParseError, "is_integer(): Wrong number of arguments "+
"given #{arguments.size} for 1")
diff --git a/lib/puppet/parser/functions/is_ip_address.rb b/lib/puppet/parser/functions/is_ip_address.rb
index a90adab..5f1d765 100644
--- a/lib/puppet/parser/functions/is_ip_address.rb
+++ b/lib/puppet/parser/functions/is_ip_address.rb
@@ -10,6 +10,8 @@ Returns true if the string passed to this function is a valid IP address.
require 'ipaddr'
+ function_deprecation([:is_ip_address, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ip_address. There is further documentation for validate_legacy function in the README.'])
+
if (arguments.size != 1) then
raise(Puppet::ParseError, "is_ip_address(): Wrong number of arguments "+
"given #{arguments.size} for 1")
diff --git a/lib/puppet/parser/functions/is_ipv4_address.rb b/lib/puppet/parser/functions/is_ipv4_address.rb
new file mode 100644
index 0000000..1764e61
--- /dev/null
+++ b/lib/puppet/parser/functions/is_ipv4_address.rb
@@ -0,0 +1,30 @@
+#
+# is_ipv4_address.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:is_ipv4_address, :type => :rvalue, :doc => <<-EOS
+Returns true if the string passed to this function is a valid IPv4 address.
+ EOS
+ ) do |arguments|
+
+ require 'ipaddr'
+
+ function_deprecation([:is_ipv4_address, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ipv4. There is further documentation for validate_legacy function in the README.'])
+
+ if (arguments.size != 1) then
+ raise(Puppet::ParseError, "is_ipv4_address(): Wrong number of arguments "+
+ "given #{arguments.size} for 1")
+ end
+
+ begin
+ ip = IPAddr.new(arguments[0])
+ rescue ArgumentError
+ return false
+ end
+
+ return ip.ipv4?
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/is_ipv6_address.rb b/lib/puppet/parser/functions/is_ipv6_address.rb
new file mode 100644
index 0000000..7ca4997
--- /dev/null
+++ b/lib/puppet/parser/functions/is_ipv6_address.rb
@@ -0,0 +1,30 @@
+#
+# is_ipv6_address.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:is_ipv6_address, :type => :rvalue, :doc => <<-EOS
+Returns true if the string passed to this function is a valid IPv6 address.
+ EOS
+ ) do |arguments|
+
+ function_deprecation([:is_ipv6_address, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ipv6. There is further documentation for validate_legacy function in the README.'])
+
+ require 'ipaddr'
+
+ if (arguments.size != 1) then
+ raise(Puppet::ParseError, "is_ipv6_address(): Wrong number of arguments "+
+ "given #{arguments.size} for 1")
+ end
+
+ begin
+ ip = IPAddr.new(arguments[0])
+ rescue ArgumentError
+ return false
+ end
+
+ return ip.ipv6?
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/is_mac_address.rb b/lib/puppet/parser/functions/is_mac_address.rb
index 1b3088a..2619d44 100644
--- a/lib/puppet/parser/functions/is_mac_address.rb
+++ b/lib/puppet/parser/functions/is_mac_address.rb
@@ -15,7 +15,7 @@ Returns true if the string passed to this function is a valid mac address.
mac = arguments[0]
- if /^[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}$/.match(mac) then
+ if /^[a-f0-9]{1,2}(:[a-f0-9]{1,2}){5}$/i.match(mac) then
return true
else
return false
diff --git a/lib/puppet/parser/functions/is_numeric.rb b/lib/puppet/parser/functions/is_numeric.rb
index e7e1d2a..4a55225 100644
--- a/lib/puppet/parser/functions/is_numeric.rb
+++ b/lib/puppet/parser/functions/is_numeric.rb
@@ -24,6 +24,8 @@ Valid examples:
EOS
) do |arguments|
+ function_deprecation([:is_numeric, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Numeric. There is further documentation for validate_legacy function in the README.'])
+
if (arguments.size != 1) then
raise(Puppet::ParseError, "is_numeric(): Wrong number of arguments "+
"given #{arguments.size} for 1")
@@ -71,5 +73,3 @@ Valid examples:
end
end
end
-
-# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/is_string.rb b/lib/puppet/parser/functions/is_string.rb
index f5bef04..31ee91e 100644
--- a/lib/puppet/parser/functions/is_string.rb
+++ b/lib/puppet/parser/functions/is_string.rb
@@ -8,12 +8,15 @@ Returns true if the variable passed to this function is a string.
EOS
) do |arguments|
+ function_deprecation([:is_string, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::String. There is further documentation for validate_legacy function in the README.'])
+
raise(Puppet::ParseError, "is_string(): Wrong number of arguments " +
"given (#{arguments.size} for 1)") if arguments.size < 1
type = arguments[0]
- result = type.is_a?(String)
+ # when called through the v4 API shim, undef gets translated to nil
+ result = type.is_a?(String) || type.nil?
if result and (type == type.to_f.to_s or type == type.to_i.to_s) then
return false
diff --git a/lib/puppet/parser/functions/join_keys_to_values.rb b/lib/puppet/parser/functions/join_keys_to_values.rb
index e9924fe..e3baf9f 100644
--- a/lib/puppet/parser/functions/join_keys_to_values.rb
+++ b/lib/puppet/parser/functions/join_keys_to_values.rb
@@ -5,7 +5,8 @@
module Puppet::Parser::Functions
newfunction(:join_keys_to_values, :type => :rvalue, :doc => <<-EOS
This function joins each key of a hash to that key's corresponding value with a
-separator. Keys and values are cast to strings. The return value is an array in
+separator. Keys are cast to strings. If values are arrays, multiple keys
+are added for each element. The return value is an array in
which each element is one joined key/value pair.
*Examples:*
@@ -13,6 +14,10 @@ which each element is one joined key/value pair.
join_keys_to_values({'a'=>1,'b'=>2}, " is ")
Would result in: ["a is 1","b is 2"]
+
+ join_keys_to_values({'a'=>1,'b'=>[2,3]}, " is ")
+
+Would result in: ["a is 1","b is 2","b is 3"]
EOS
) do |arguments|
@@ -38,8 +43,12 @@ Would result in: ["a is 1","b is 2"]
# Join the keys to their values.
hash.map do |k,v|
- String(k) + separator + String(v)
- end
+ if v.is_a?(Array)
+ v.map { |va| String(k) + separator + String(va) }
+ else
+ String(k) + separator + String(v)
+ end
+ end.flatten
end
end
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..c9b8488
--- /dev/null
+++ b/lib/puppet/parser/functions/load_module_metadata.rb
@@ -0,0 +1,24 @@
+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 or two") unless [1,2].include?(args.size)
+ mod = args[0]
+ allow_empty_metadata = args[1]
+ module_path = function_get_module_path([mod])
+ metadata_json = File.join(module_path, 'metadata.json')
+
+ metadata_exists = File.exists?(metadata_json)
+ if metadata_exists
+ metadata = PSON.load(File.read(metadata_json))
+ else
+ if allow_empty_metadata
+ metadata = {}
+ else
+ raise(Puppet::ParseError, "load_module_metadata(): No metadata.json file for module #{mod}")
+ end
+ end
+
+ return metadata
+ end
+end
diff --git a/lib/puppet/parser/functions/loadjson.rb b/lib/puppet/parser/functions/loadjson.rb
new file mode 100644
index 0000000..3a3372b
--- /dev/null
+++ b/lib/puppet/parser/functions/loadjson.rb
@@ -0,0 +1,34 @@
+module Puppet::Parser::Functions
+ newfunction(:loadjson, :type => :rvalue, :arity => -2, :doc => <<-'ENDHEREDOC') do |args|
+Load a JSON file containing an array, string, or hash, and return the data
+in the corresponding native data type.
+The second parameter is the default value. It will be returned if the file
+was not found or could not be parsed.
+
+For example:
+
+ $myhash = loadjson('/etc/puppet/data/myhash.json')
+ $myhash = loadjson('no-file.json', {'default' => 'value'})
+ ENDHEREDOC
+
+ raise ArgumentError, 'Wrong number of arguments. 1 or 2 arguments should be provided.' unless args.length >= 1
+
+ if File.exists?(args[0])
+ begin
+ content = File.read(args[0])
+ PSON::load(content) || args[1]
+ rescue Exception => e
+ if args[1]
+ args[1]
+ else
+ raise e
+ end
+ end
+ else
+ warning("Can't load '#{args[0]}' File does not exist!")
+ args[1]
+ end
+
+ end
+
+end
diff --git a/lib/puppet/parser/functions/loadyaml.rb b/lib/puppet/parser/functions/loadyaml.rb
index 10c4005..9696362 100644
--- a/lib/puppet/parser/functions/loadyaml.rb
+++ b/lib/puppet/parser/functions/loadyaml.rb
@@ -1,20 +1,34 @@
module Puppet::Parser::Functions
+ newfunction(:loadyaml, :type => :rvalue, :arity => -2, :doc => <<-'ENDHEREDOC') do |args|
+Load a YAML file containing an array, string, or hash, and return the data
+in the corresponding native data type.
+The second parameter is the default value. It will be returned if the file
+was not found or could not be parsed.
- newfunction(:loadyaml, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
- Load a YAML file containing an array, string, or hash, and return the data
- in the corresponding native data type.
+For example:
- For example:
+ $myhash = loadyaml('/etc/puppet/data/myhash.yaml')
+ $myhash = loadyaml('no-file.yaml', {'default' => 'value'})
+ ENDHEREDOC
- $myhash = loadyaml('/etc/puppet/data/myhash.yaml')
- ENDHEREDOC
+ raise ArgumentError, 'Wrong number of arguments. 1 or 2 arguments should be provided.' unless args.length >= 1
+ require 'yaml'
- unless args.length == 1
- raise Puppet::ParseError, ("loadyaml(): wrong number of arguments (#{args.length}; must be 1)")
+ if File.exists?(args[0])
+ begin
+ YAML::load_file(args[0]) || args[1]
+ rescue Exception => e
+ if args[1]
+ args[1]
+ else
+ raise e
+ end
+ end
+ else
+ warning("Can't load '#{args[0]}' File does not exist!")
+ args[1]
end
- YAML.load_file(args[0])
-
end
end
diff --git a/lib/puppet/parser/functions/member.rb b/lib/puppet/parser/functions/member.rb
index 88609ce..1e5b3de 100644
--- a/lib/puppet/parser/functions/member.rb
+++ b/lib/puppet/parser/functions/member.rb
@@ -44,7 +44,7 @@ would return: false
end
if arguments[1].is_a? String or arguments[1].is_a? Fixnum
- item = Array(arguments[1])
+ item = [arguments[1]]
else
item = arguments[1]
end
diff --git a/lib/puppet/parser/functions/parsejson.rb b/lib/puppet/parser/functions/parsejson.rb
index a9a16a4..f7c2896 100644
--- a/lib/puppet/parser/functions/parsejson.rb
+++ b/lib/puppet/parser/functions/parsejson.rb
@@ -4,20 +4,25 @@
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
+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 StandardError => e
+ if arguments[1]
+ arguments[1]
+ else
+ raise e
+ end
end
- json = arguments[0]
-
- # PSON is natively available in puppet
- PSON.load(json)
end
end
diff --git a/lib/puppet/parser/functions/parseyaml.rb b/lib/puppet/parser/functions/parseyaml.rb
index 53d54fa..ba9d98a 100644
--- a/lib/puppet/parser/functions/parseyaml.rb
+++ b/lib/puppet/parser/functions/parseyaml.rb
@@ -6,17 +6,26 @@ module Puppet::Parser::Functions
newfunction(:parseyaml, :type => :rvalue, :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]
+ # in ruby 1.9.3 Psych::SyntaxError is a RuntimeException
+ # this still needs to catch that and work also on rubies that
+ # do not have Psych available.
+ rescue StandardError, Psych::SyntaxError => e
+ if arguments[1]
+ arguments[1]
+ else
+ raise e
+ end
+ end
end
end
diff --git a/lib/puppet/parser/functions/prefix.rb b/lib/puppet/parser/functions/prefix.rb
index d02286a..ac1c58a 100644
--- a/lib/puppet/parser/functions/prefix.rb
+++ b/lib/puppet/parser/functions/prefix.rb
@@ -4,7 +4,7 @@
module Puppet::Parser::Functions
newfunction(:prefix, :type => :rvalue, :doc => <<-EOS
-This function applies a prefix to all elements in an array.
+This function applies a prefix to all elements in an array or a hash.
*Examples:*
@@ -18,10 +18,10 @@ Will return: ['pa','pb','pc']
raise(Puppet::ParseError, "prefix(): Wrong number of arguments " +
"given (#{arguments.size} for 1)") if arguments.size < 1
- array = arguments[0]
+ enumerable = arguments[0]
- unless array.is_a?(Array)
- raise Puppet::ParseError, "prefix(): expected first argument to be an Array, got #{array.inspect}"
+ unless enumerable.is_a?(Array) or enumerable.is_a?(Hash)
+ raise Puppet::ParseError, "prefix(): expected first argument to be an Array or a Hash, got #{enumerable.inspect}"
end
prefix = arguments[1] if arguments[1]
@@ -32,10 +32,17 @@ Will return: ['pa','pb','pc']
end
end
- # Turn everything into string same as join would do ...
- result = array.collect do |i|
- i = i.to_s
- prefix ? prefix + i : i
+ if enumerable.is_a?(Array)
+ # Turn everything into string same as join would do ...
+ result = enumerable.collect do |i|
+ i = i.to_s
+ prefix ? prefix + i : i
+ end
+ else
+ result = Hash[enumerable.map do |k,v|
+ k = k.to_s
+ [ prefix ? prefix + k : k, v ]
+ end]
end
return result
diff --git a/lib/puppet/parser/functions/private.rb b/lib/puppet/parser/functions/private.rb
index 60210d3..3b00ba1 100644
--- a/lib/puppet/parser/functions/private.rb
+++ b/lib/puppet/parser/functions/private.rb
@@ -4,26 +4,14 @@
module Puppet::Parser::Functions
newfunction(:private, :doc => <<-'EOS'
- Sets the current class or definition as private.
+ DEPRECATED: Sets the current class or definition as private.
Calling the class or definition from outside the current module will fail.
- EOS
+ EOS
) do |args|
-
- raise(Puppet::ParseError, "private(): Wrong number of arguments "+
- "given (#{args.size}}) for 0 or 1)") if args.size > 1
-
- scope = self
- if scope.lookupvar('module_name') != scope.lookupvar('caller_module_name')
- message = nil
- if args[0] and args[0].is_a? String
- message = args[0]
- else
- manifest_name = scope.source.name
- manifest_type = scope.source.type
- message = (manifest_type.to_s == 'hostclass') ? 'Class' : 'Definition'
- message += " #{manifest_name} is private"
- end
- raise(Puppet::ParseError, message)
+ warning("private() DEPRECATED: This function will cease to function on Puppet 4; please use assert_private() before upgrading to puppet 4 for backwards-compatibility, or migrate to the new parser's typing system.")
+ if !Puppet::Parser::Functions.autoloader.loaded?(:assert_private)
+ Puppet::Parser::Functions.autoloader.load(:assert_private)
end
+ function_assert_private([(args[0] unless args.size < 1)])
end
end
diff --git a/lib/puppet/parser/functions/pry.rb b/lib/puppet/parser/functions/pry.rb
new file mode 100644
index 0000000..c18ef7e
--- /dev/null
+++ b/lib/puppet/parser/functions/pry.rb
@@ -0,0 +1,30 @@
+#
+# pry.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:pry, :type => :statement, :doc => <<-EOS
+This function invokes a pry debugging session in the current scope object. This is useful for debugging manifest code at specific points during a compilation.
+
+*Examples:*
+
+ pry()
+ EOS
+ ) do |arguments|
+ begin
+ require 'pry'
+ rescue LoadError
+ raise(Puppet::Error, "pry(): Requires the 'pry' rubygem to use, but it was not found")
+ end
+ #
+ ## Run `catalog` to see the contents currently compiling catalog
+ ## Run `cd catalog` and `ls` to see catalog methods and instance variables
+ ## Run `@resource_table` to see the current catalog resource table
+ #
+ if $stdout.isatty
+ binding.pry # rubocop:disable Lint/Debugger
+ else
+ Puppet.warning 'pry(): cowardly refusing to start the debugger on a daemonized master'
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/pw_hash.rb b/lib/puppet/parser/functions/pw_hash.rb
new file mode 100644
index 0000000..41d4223
--- /dev/null
+++ b/lib/puppet/parser/functions/pw_hash.rb
@@ -0,0 +1,56 @@
+Puppet::Parser::Functions::newfunction(
+ :pw_hash,
+ :type => :rvalue,
+ :arity => 3,
+ :doc => "Hashes a password using the crypt function. Provides a hash
+ usable on most POSIX systems.
+
+ The first argument to this function is the password to hash. If it is
+ undef or an empty string, this function returns undef.
+
+ The second argument to this function is which type of hash to use. It
+ will be converted into the appropriate crypt(3) hash specifier. Valid
+ hash types are:
+
+ |Hash type |Specifier|
+ |---------------------|---------|
+ |MD5 |1 |
+ |SHA-256 |5 |
+ |SHA-512 (recommended)|6 |
+
+ The third argument to this function is the salt to use.
+
+ 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.") do |args|
+ raise ArgumentError, "pw_hash(): wrong number of arguments (#{args.size} for 3)" if args.size != 3
+ raise ArgumentError, "pw_hash(): first argument must be a string" unless args[0].is_a? String or args[0].nil?
+ raise ArgumentError, "pw_hash(): second argument must be a string" unless args[1].is_a? String
+ hashes = { 'md5' => '1',
+ 'sha-256' => '5',
+ 'sha-512' => '6' }
+ hash_type = hashes[args[1].downcase]
+ raise ArgumentError, "pw_hash(): #{args[1]} is not a valid hash type" if hash_type.nil?
+ raise ArgumentError, "pw_hash(): third argument must be a string" unless args[2].is_a? String
+ raise ArgumentError, "pw_hash(): third argument must not be empty" if args[2].empty?
+ raise ArgumentError, "pw_hash(): characters in salt must be in the set [a-zA-Z0-9./]" unless args[2].match(/\A[a-zA-Z0-9.\/]+\z/)
+
+ password = args[0]
+ return nil if password.nil? or password.empty?
+
+ salt = "$#{hash_type}$#{args[2]}"
+
+ # handle weak implementations of String#crypt
+ if 'test'.crypt('$1$1') != '$1$1$Bp8CU9Oujr9SSEw53WV6G.'
+ # JRuby < 1.7.17
+ if RUBY_PLATFORM == 'java'
+ # puppetserver bundles Apache Commons Codec
+ org.apache.commons.codec.digest.Crypt.crypt(password.to_java_bytes, salt)
+ else
+ # MS Windows and other systems that don't support enhanced salts
+ raise Puppet::ParseError, 'system does not support enhanced salts'
+ end
+ else
+ password.crypt(salt)
+ end
+end
diff --git a/lib/puppet/parser/functions/range.rb b/lib/puppet/parser/functions/range.rb
index 49fba21..d690df7 100644
--- a/lib/puppet/parser/functions/range.rb
+++ b/lib/puppet/parser/functions/range.rb
@@ -25,8 +25,8 @@ integers automatically)
Will return: ["a","b","c"]
range("host01", "host10")
-
Will return: ["host01", "host02", ..., "host09", "host10"]
+NB Be explicit in including trailing zeros. Otherwise the underlying ruby function will fail.
Passing a third argument will cause the generated range to step by that
interval, e.g.
@@ -37,18 +37,17 @@ Will return: [0,2,4,6,8]
EOS
) do |arguments|
- # We support more than one argument but at least one is mandatory ...
- raise(Puppet::ParseError, "range(): Wrong number of " +
- "arguments given (#{arguments.size} for 1)") if arguments.size < 1
+ raise(Puppet::ParseError, 'range(): Wrong number of ' +
+ 'arguments given (0 for 1)') if arguments.size == 0
if arguments.size > 1
start = arguments[0]
stop = arguments[1]
step = arguments[2].nil? ? 1 : arguments[2].to_i.abs
- type = '..' # We select simplest type for Range available in Ruby ...
+ type = '..' # Use the simplest type of Range available in Ruby
- elsif arguments.size > 0
+ else # arguments.size == 1
value = arguments[0]
if m = value.match(/^(\w+)(\.\.\.?|\-)(\w+)$/)
@@ -56,16 +55,16 @@ Will return: [0,2,4,6,8]
stop = m[3]
type = m[2]
-
+ step = 1
elsif value.match(/^.+$/)
- raise(Puppet::ParseError, 'range(): Unable to compute range ' +
- 'from the value given')
+ raise(Puppet::ParseError, "range(): Unable to compute range " +
+ "from the value: #{value}")
else
- raise(Puppet::ParseError, 'range(): Unknown format of range given')
+ raise(Puppet::ParseError, "range(): Unknown range format: #{value}")
end
end
- # Check whether we have integer value if so then make it so ...
+ # If we were given an integer, ensure we work with one
if start.to_s.match(/^\d+$/)
start = start.to_i
stop = stop.to_i
@@ -76,10 +75,10 @@ Will return: [0,2,4,6,8]
range = case type
when /^(\.\.|\-)$/ then (start .. stop)
- when /^(\.\.\.)$/ then (start ... stop) # Exclusive of last element ...
+ when '...' then (start ... stop) # Exclusive of last element
end
- result = range.step(step).collect { |i| i } # Get them all ... Pokemon ...
+ result = range.step(step).to_a
return result
end
diff --git a/lib/puppet/parser/functions/regexpescape.rb b/lib/puppet/parser/functions/regexpescape.rb
new file mode 100644
index 0000000..477ee87
--- /dev/null
+++ b/lib/puppet/parser/functions/regexpescape.rb
@@ -0,0 +1,31 @@
+#
+# regexpescape.rb
+#
+module Puppet::Parser::Functions
+ newfunction(:regexpescape, :type => :rvalue, :doc => <<-EOS
+ Regexp escape a string or array of strings.
+ Requires either a single string or an array as an input.
+ EOS
+ ) do |arguments| # rubocop:disable Style/ClosingParenthesisIndentation
+ raise(Puppet::ParseError, 'regexpescape(): Wrong number of arguments ' \
+ "given (#{arguments.size} for 1)") if arguments.empty?
+
+ value = arguments[0]
+
+ unless value.is_a?(Array) || value.is_a?(String)
+ raise(Puppet::ParseError, 'regexpescape(): Requires either ' \
+ 'array or string to work with')
+ end
+
+ result = if value.is_a?(Array)
+ # Numbers in Puppet are often string-encoded which is troublesome ...
+ value.collect { |i| i.is_a?(String) ? Regexp.escape(i) : i }
+ else
+ Regexp.escape(value)
+ end
+
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/seeded_rand.rb b/lib/puppet/parser/functions/seeded_rand.rb
new file mode 100644
index 0000000..44e27b8
--- /dev/null
+++ b/lib/puppet/parser/functions/seeded_rand.rb
@@ -0,0 +1,22 @@
+Puppet::Parser::Functions::newfunction(
+ :seeded_rand,
+ :arity => 2,
+ :type => :rvalue,
+ :doc => <<-EOS
+Usage: `seeded_rand(MAX, SEED)`. MAX must be a positive integer; SEED is any string.
+
+Generates a random whole number greater than or equal to 0 and less
+than MAX, using the value of SEED for repeatable randomness. If SEED
+starts with "$fqdn:", this is behaves the same as `fqdn_rand`.
+
+EOS
+) do |args|
+ require 'digest/md5'
+
+ raise(ArgumentError, "seeded_rand(): first argument must be a positive integer") unless function_is_integer([args[0]]) and args[0].to_i > 0
+ raise(ArgumentError, "seeded_rand(): second argument must be a string") unless args[1].is_a? String
+
+ max = args[0].to_i
+ seed = Digest::MD5.hexdigest(args[1]).hex
+ Puppet::Util.deterministic_rand(seed,max)
+end
diff --git a/lib/puppet/parser/functions/shell_escape.rb b/lib/puppet/parser/functions/shell_escape.rb
new file mode 100644
index 0000000..447fe35
--- /dev/null
+++ b/lib/puppet/parser/functions/shell_escape.rb
@@ -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 :
diff --git a/lib/puppet/parser/functions/shell_join.rb b/lib/puppet/parser/functions/shell_join.rb
new file mode 100644
index 0000000..05aeb95
--- /dev/null
+++ b/lib/puppet/parser/functions/shell_join.rb
@@ -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 :
diff --git a/lib/puppet/parser/functions/shell_split.rb b/lib/puppet/parser/functions/shell_split.rb
new file mode 100644
index 0000000..0446448
--- /dev/null
+++ b/lib/puppet/parser/functions/shell_split.rb
@@ -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 :
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/str2bool.rb b/lib/puppet/parser/functions/str2bool.rb
index 446732e..472506d 100644
--- a/lib/puppet/parser/functions/str2bool.rb
+++ b/lib/puppet/parser/functions/str2bool.rb
@@ -5,8 +5,8 @@
module Puppet::Parser::Functions
newfunction(:str2bool, :type => :rvalue, :doc => <<-EOS
This converts a string to a boolean. This attempt to convert strings that
-contain things like: y, 1, t, true to 'true' and strings that contain things
-like: 0, f, n, false, no to 'false'.
+contain things like: Y,y, 1, T,t, TRUE,true to 'true' and strings that contain things
+like: 0, F,f, N,n, false, FALSE, no to 'false'.
EOS
) do |arguments|
@@ -21,7 +21,7 @@ like: 0, f, n, false, no to 'false'.
end
unless string.is_a?(String)
- raise(Puppet::ParseError, 'str2bool(): Requires either ' +
+ raise(Puppet::ParseError, 'str2bool(): Requires ' +
'string to work with')
end
@@ -32,8 +32,8 @@ like: 0, f, n, false, no to 'false'.
# We yield false in this case.
#
when /^$/, '' then false # Empty string will be false ...
- when /^(1|t|y|true|yes)$/ then true
- when /^(0|f|n|false|no)$/ then false
+ when /^(1|t|y|true|yes)$/i then true
+ when /^(0|f|n|false|no)$/i then false
when /^(undef|undefined)$/ then false # This is not likely to happen ...
else
raise(Puppet::ParseError, 'str2bool(): Unknown type of boolean given')
diff --git a/lib/puppet/parser/functions/suffix.rb b/lib/puppet/parser/functions/suffix.rb
index f7792d6..2908434 100644
--- a/lib/puppet/parser/functions/suffix.rb
+++ b/lib/puppet/parser/functions/suffix.rb
@@ -4,7 +4,8 @@
module Puppet::Parser::Functions
newfunction(:suffix, :type => :rvalue, :doc => <<-EOS
-This function applies a suffix to all elements in an array.
+This function applies a suffix to all elements in an array, or to the keys
+in a hash.
*Examples:*
@@ -18,10 +19,10 @@ Will return: ['ap','bp','cp']
raise(Puppet::ParseError, "suffix(): Wrong number of arguments " +
"given (#{arguments.size} for 1)") if arguments.size < 1
- array = arguments[0]
+ enumerable = arguments[0]
- unless array.is_a?(Array)
- raise Puppet::ParseError, "suffix(): expected first argument to be an Array, got #{array.inspect}"
+ unless enumerable.is_a?(Array) or enumerable.is_a?(Hash)
+ raise Puppet::ParseError, "suffix(): expected first argument to be an Array or a Hash, got #{enumerable.inspect}"
end
suffix = arguments[1] if arguments[1]
@@ -32,10 +33,17 @@ Will return: ['ap','bp','cp']
end
end
- # Turn everything into string same as join would do ...
- result = array.collect do |i|
- i = i.to_s
- suffix ? i + suffix : i
+ if enumerable.is_a?(Array)
+ # Turn everything into string same as join would do ...
+ result = enumerable.collect do |i|
+ i = i.to_s
+ suffix ? i + suffix : i
+ end
+ else
+ result = Hash[enumerable.map do |k,v|
+ k = k.to_s
+ [ suffix ? k + suffix : k, v ]
+ end]
end
return result
diff --git a/lib/puppet/parser/functions/time.rb b/lib/puppet/parser/functions/time.rb
index 0cddaf8..c574747 100644
--- a/lib/puppet/parser/functions/time.rb
+++ b/lib/puppet/parser/functions/time.rb
@@ -33,13 +33,14 @@ Will return something like: 1311972653
ENV['TZ'] = time_zone
- time = local_time.localtime
+ result = local_time.localtime.strftime('%s')
ENV['TZ'] = original_zone
+ else
+ result = time.localtime.strftime('%s')
end
# Calling Time#to_i on a receiver changes it. Trust me I am the Doctor.
- result = time.strftime('%s')
result = result.to_i
return result
diff --git a/lib/puppet/parser/functions/try_get_value.rb b/lib/puppet/parser/functions/try_get_value.rb
new file mode 100644
index 0000000..fc19a23
--- /dev/null
+++ b/lib/puppet/parser/functions/try_get_value.rb
@@ -0,0 +1,53 @@
+module Puppet::Parser::Functions
+ newfunction(
+ :try_get_value,
+ :type => :rvalue,
+ :arity => -2,
+ :doc => <<-eos
+DEPRECATED: this function is deprecated, please use dig() instead.
+
+Looks up into a complex structure of arrays and hashes and returns a value
+or the default value if nothing was found.
+
+Key can contain slashes to describe path components. The function will go down
+the structure and try to extract the required value.
+
+$data = {
+ 'a' => {
+ 'b' => [
+ 'b1',
+ 'b2',
+ 'b3',
+ ]
+ }
+}
+
+$value = try_get_value($data, 'a/b/2', 'not_found', '/')
+=> $value = 'b3'
+
+a -> first hash key
+b -> second hash key
+2 -> array index starting with 0
+
+not_found -> (optional) will be returned if there is no value or the path did not match. Defaults to nil.
+/ -> (optional) path delimiter. Defaults to '/'.
+
+In addition to the required "key" argument, "try_get_value" accepts default
+argument. It will be returned if no value was found or a path component is
+missing. And the fourth argument can set a variable path separator.
+ eos
+ ) do |args|
+ warning("try_get_value() DEPRECATED: this function is deprecated, please use dig() instead.")
+ data = args[0]
+ path = args[1] || ''
+ default = args[2]
+
+ if !(data.is_a?(Hash) || data.is_a?(Array)) || path == ''
+ return default || data
+ end
+
+ separator = args[3] || '/'
+ path = path.split(separator).map{ |key| key =~ /^\d+$/ ? key.to_i : key }
+ function_dig([data, path, default])
+ end
+end
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 4302b29..44b3bcd 100644
--- a/lib/puppet/parser/functions/upcase.rb
+++ b/lib/puppet/parser/functions/upcase.rb
@@ -12,23 +12,28 @@ Converts a string or an array of strings to uppercase.
Will return:
- ASDF
- EOS
+ ABCD
+ EOS
) do |arguments|
raise(Puppet::ParseError, "upcase(): Wrong number of arguments " +
- "given (#{arguments.size} for 1)") if arguments.size < 1
+ "given (#{arguments.size} for 1)") if arguments.size != 1
value = arguments[0]
- unless value.is_a?(Array) || value.is_a?(String)
- raise(Puppet::ParseError, 'upcase(): Requires either ' +
- 'array or string to work with')
+ unless value.is_a?(Array) || value.is_a?(Hash) || value.respond_to?(:upcase)
+ raise(Puppet::ParseError, 'upcase(): Requires an ' +
+ 'array, hash or object that responds to upcase in order to work')
end
if value.is_a?(Array)
# Numbers in Puppet are often string-encoded which is troublesome ...
- result = value.collect { |i| i.is_a?(String) ? i.upcase : i }
+ result = value.collect { |i| function_upcase([i]) }
+ elsif value.is_a?(Hash)
+ result = {}
+ value.each_pair do |k, v|
+ result[function_upcase([k])] = function_upcase([v])
+ end
else
result = value.upcase
end
diff --git a/lib/puppet/parser/functions/uriescape.rb b/lib/puppet/parser/functions/uriescape.rb
index a486eee..45bbed2 100644
--- a/lib/puppet/parser/functions/uriescape.rb
+++ b/lib/puppet/parser/functions/uriescape.rb
@@ -22,7 +22,7 @@ module Puppet::Parser::Functions
if value.is_a?(Array)
# Numbers in Puppet are often string-encoded which is troublesome ...
- result = value.collect { |i| i.is_a?(String) ? URI.escape(i,unsafe) : i }
+ result = value.collect { |i| i.is_a?(String) ? URI.escape(i) : i }
else
result = URI.escape(value)
end
diff --git a/lib/puppet/parser/functions/validate_absolute_path.rb b/lib/puppet/parser/functions/validate_absolute_path.rb
index b696680..c73f3df 100644
--- a/lib/puppet/parser/functions/validate_absolute_path.rb
+++ b/lib/puppet/parser/functions/validate_absolute_path.rb
@@ -26,6 +26,9 @@ module Puppet::Parser::Functions
ENDHEREDOC
+ # The deprecation function was being called twice, as validate_absolute_path calls is_absolute_path. I have removed it from here so it only calls deprecation once within is_absolute_path.
+ # function_deprecation([:validate_absolute_path, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Absolute_path. There is further documentation for validate_legacy function in the README.'])
+
require 'puppet/util'
unless args.length > 0 then
@@ -40,28 +43,10 @@ module Puppet::Parser::Functions
unless arg.is_a?(Array) then
candidates = Array.new(1,arg)
end
- # iterate over all pathes within the candidates array
+ # iterate over all paths within the candidates array
candidates.each do |path|
- # This logic was borrowed from
- # [lib/puppet/file_serving/base.rb](https://github.com/puppetlabs/puppet/blob/master/lib/puppet/file_serving/base.rb)
- # Puppet 2.7 and beyond will have Puppet::Util.absolute_path? Fall back to a back-ported implementation otherwise.
- if Puppet::Util.respond_to?(:absolute_path?) then
- unless Puppet::Util.absolute_path?(path, :posix) or Puppet::Util.absolute_path?(path, :windows)
- raise Puppet::ParseError, ("#{path.inspect} is not an absolute path.")
- end
- else
- # This code back-ported from 2.7.x's lib/puppet/util.rb Puppet::Util.absolute_path?
- # Determine in a platform-specific way whether a path is absolute. This
- # defaults to the local platform if none is specified.
- # Escape once for the string literal, and once for the regex.
- slash = '[\\\\/]'
- name = '[^\\\\/]+'
- regexes = {
- :windows => %r!^(([A-Z]:#{slash})|(#{slash}#{slash}#{name}#{slash}#{name})|(#{slash}#{slash}\?#{slash}#{name}))!i,
- :posix => %r!^/!,
- }
- rval = (!!(path =~ regexes[:posix])) || (!!(path =~ regexes[:windows]))
- rval or raise Puppet::ParseError, ("#{path.inspect} is not an absolute path.")
+ unless function_is_absolute_path([path])
+ raise Puppet::ParseError, ("#{path.inspect} is not an absolute path.")
end
end
end
diff --git a/lib/puppet/parser/functions/validate_array.rb b/lib/puppet/parser/functions/validate_array.rb
index 34b5118..3bf3983 100644
--- a/lib/puppet/parser/functions/validate_array.rb
+++ b/lib/puppet/parser/functions/validate_array.rb
@@ -18,6 +18,8 @@ module Puppet::Parser::Functions
ENDHEREDOC
+ function_deprecation([:validate_array, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Array. There is further documentation for validate_legacy function in the README.'])
+
unless args.length > 0 then
raise Puppet::ParseError, ("validate_array(): wrong number of arguments (#{args.length}; must be > 0)")
end
diff --git a/lib/puppet/parser/functions/validate_augeas.rb b/lib/puppet/parser/functions/validate_augeas.rb
index 4ea4fe0..2196c3e 100644
--- a/lib/puppet/parser/functions/validate_augeas.rb
+++ b/lib/puppet/parser/functions/validate_augeas.rb
@@ -31,7 +31,7 @@ module Puppet::Parser::Functions
ENDHEREDOC
unless Puppet.features.augeas?
- raise Puppet::ParseError, ("validate_augeas(): this function requires the augeas feature. See http://projects.puppetlabs.com/projects/puppet/wiki/Puppet_Augeas#Pre-requisites for how to activate it.")
+ raise Puppet::ParseError, ("validate_augeas(): this function requires the augeas feature. See http://docs.puppetlabs.com/guides/augeas.html#pre-requisites for how to activate it.")
end
if (args.length < 2) or (args.length > 4) then
diff --git a/lib/puppet/parser/functions/validate_bool.rb b/lib/puppet/parser/functions/validate_bool.rb
index 59a0805..49075b8 100644
--- a/lib/puppet/parser/functions/validate_bool.rb
+++ b/lib/puppet/parser/functions/validate_bool.rb
@@ -19,6 +19,9 @@ module Puppet::Parser::Functions
ENDHEREDOC
+ # The deprecation function was being called twice, as validate_bool calls is_bool. I have removed it from here so it only calls deprecation once within is_bool.
+ # function_deprecation([:validate_bool, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Bool. There is further documentation for validate_legacy function in the README.'])
+
unless args.length > 0 then
raise Puppet::ParseError, ("validate_bool(): wrong number of arguments (#{args.length}; must be > 0)")
end
diff --git a/lib/puppet/parser/functions/validate_cmd.rb b/lib/puppet/parser/functions/validate_cmd.rb
index 5df3c60..685162b 100644
--- a/lib/puppet/parser/functions/validate_cmd.rb
+++ b/lib/puppet/parser/functions/validate_cmd.rb
@@ -53,7 +53,7 @@ module Puppet::Parser::Functions
rescue Puppet::ExecutionFailure => detail
msg += "\n#{detail}"
raise Puppet::ParseError, msg
- rescue Exception => detail
+ rescue StandardError => detail
msg += "\n#{detail.class.name} #{detail}"
raise Puppet::ParseError, msg
ensure
diff --git a/lib/puppet/parser/functions/validate_email_address.rb b/lib/puppet/parser/functions/validate_email_address.rb
new file mode 100644
index 0000000..ddd0d25
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_email_address.rb
@@ -0,0 +1,31 @@
+module Puppet::Parser::Functions
+ newfunction(:validate_email_address, :doc => <<-ENDHEREDOC
+ Validate that all values passed are valid email addresses.
+ Fail compilation if any value fails this check.
+ The following values will pass:
+ $my_email = "waldo@gmail.com"
+ validate_email_address($my_email)
+ validate_email_address("bob@gmail.com", "alice@gmail.com", $my_email)
+
+ The following values will fail, causing compilation to abort:
+ $some_array = [ 'bad_email@/d/efdf.com' ]
+ validate_email_address($some_array)
+ ENDHEREDOC
+ ) do |args|
+ rescuable_exceptions = [ArgumentError]
+
+ if args.empty?
+ raise Puppet::ParseError, "validate_email_address(): wrong number of arguments (#{args.length}; must be > 0)"
+ end
+
+ args.each do |arg|
+ raise Puppet::ParseError, "#{arg.inspect} is not a string." unless arg.is_a?(String)
+
+ begin
+ raise Puppet::ParseError, "#{arg.inspect} is not a valid email address" unless function_is_email_address([arg])
+ rescue *rescuable_exceptions
+ raise Puppet::ParseError, "#{arg.inspect} is not a valid email address"
+ end
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/validate_hash.rb b/lib/puppet/parser/functions/validate_hash.rb
index 9bdd543..fcdc7e1 100644
--- a/lib/puppet/parser/functions/validate_hash.rb
+++ b/lib/puppet/parser/functions/validate_hash.rb
@@ -18,6 +18,8 @@ module Puppet::Parser::Functions
ENDHEREDOC
+ function_deprecation([:validate_hash, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Hash. There is further documentation for validate_legacy function in the README.'])
+
unless args.length > 0 then
raise Puppet::ParseError, ("validate_hash(): wrong number of arguments (#{args.length}; must be > 0)")
end
diff --git a/lib/puppet/parser/functions/validate_integer.rb b/lib/puppet/parser/functions/validate_integer.rb
new file mode 100644
index 0000000..2ae0293
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_integer.rb
@@ -0,0 +1,134 @@
+module Puppet::Parser::Functions
+
+ newfunction(:validate_integer, :doc => <<-'ENDHEREDOC') do |args|
+ Validate that the first argument is an integer (or an array of integers). Abort catalog compilation if any of the checks fail.
+
+ The second argument is optional and passes a maximum. (All elements of) the first argument has to be less or equal to this max.
+
+ The third argument is optional and passes a minimum. (All elements of) the first argument has to be greater or equal to this min.
+ If, and only if, a minimum is given, the second argument may be an empty string or undef, which will be handled to just check
+ if (all elements of) the first argument are greater or equal to the given minimum.
+
+ It will fail if the first argument is not an integer or array of integers, and if arg 2 and arg 3 are not convertable to an integer.
+
+ The following values will pass:
+
+ validate_integer(1)
+ validate_integer(1, 2)
+ validate_integer(1, 1)
+ validate_integer(1, 2, 0)
+ validate_integer(2, 2, 2)
+ validate_integer(2, '', 0)
+ validate_integer(2, undef, 0)
+ $foo = undef
+ validate_integer(2, $foo, 0)
+ validate_integer([1,2,3,4,5], 6)
+ validate_integer([1,2,3,4,5], 6, 0)
+
+ Plus all of the above, but any combination of values passed as strings ('1' or "1").
+ Plus all of the above, but with (correct) combinations of negative integer values.
+
+ The following values will not:
+
+ validate_integer(true)
+ validate_integer(false)
+ validate_integer(7.0)
+ validate_integer({ 1 => 2 })
+ $foo = undef
+ validate_integer($foo)
+ validate_integer($foobaridontexist)
+
+ validate_integer(1, 0)
+ validate_integer(1, true)
+ validate_integer(1, '')
+ validate_integer(1, undef)
+ validate_integer(1, , 0)
+ validate_integer(1, 2, 3)
+ validate_integer(1, 3, 2)
+ validate_integer(1, 3, true)
+
+ 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 items in arrays or maximum / minimum argument.
+
+ ENDHEREDOC
+
+ function_deprecation([:validate_integer, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Integer. There is further documentation for validate_legacy function in the README.'])
+
+ # tell the user we need at least one, and optionally up to two other parameters
+ raise Puppet::ParseError, "validate_integer(): Wrong number of arguments; must be 1, 2 or 3, got #{args.length}" unless args.length > 0 and args.length < 4
+
+ input, max, min = *args
+
+ # check maximum parameter
+ if args.length > 1
+ max = max.to_s
+ # allow max to be empty (or undefined) if we have a minimum set
+ if args.length > 2 and max == ''
+ max = nil
+ else
+ begin
+ max = Integer(max)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_integer(): Expected second argument to be unset or an Integer, got #{max}:#{max.class}"
+ end
+ end
+ else
+ max = nil
+ end
+
+ # check minimum parameter
+ if args.length > 2
+ begin
+ min = Integer(min.to_s)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_integer(): Expected third argument to be unset or an Integer, got #{min}:#{min.class}"
+ end
+ else
+ min = nil
+ end
+
+ # ensure that min < max
+ if min and max and min > max
+ raise Puppet::ParseError, "validate_integer(): Expected second argument to be larger than third argument, got #{max} < #{min}"
+ end
+
+ # create lamba validator function
+ validator = lambda do |num|
+ # check input < max
+ if max and num > max
+ raise Puppet::ParseError, "validate_integer(): Expected #{input.inspect} to be smaller or equal to #{max}, got #{input.inspect}."
+ end
+ # check input > min (this will only be checked if no exception has been raised before)
+ if min and num < min
+ raise Puppet::ParseError, "validate_integer(): Expected #{input.inspect} to be greater or equal to #{min}, got #{input.inspect}."
+ end
+ end
+
+ # if this is an array, handle it.
+ case input
+ when Array
+ # check every element of the array
+ input.each_with_index do |arg, pos|
+ begin
+ raise TypeError if arg.is_a?(Hash)
+ arg = Integer(arg.to_s)
+ validator.call(arg)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_integer(): Expected element at array position #{pos} to be an Integer, got #{arg.class}"
+ end
+ end
+ # for the sake of compatibility with ruby 1.8, we need extra handling of hashes
+ when Hash
+ raise Puppet::ParseError, "validate_integer(): Expected first argument to be an Integer or Array, got #{input.class}"
+ # check the input. this will also fail any stuff other than pure, shiny integers
+ else
+ begin
+ input = Integer(input.to_s)
+ validator.call(input)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_integer(): Expected first argument to be an Integer or Array, got #{input.class}"
+ end
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/validate_ip_address.rb b/lib/puppet/parser/functions/validate_ip_address.rb
new file mode 100644
index 0000000..5d80cfb
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_ip_address.rb
@@ -0,0 +1,52 @@
+module Puppet::Parser::Functions
+
+ newfunction(:validate_ip_address, :doc => <<-ENDHEREDOC
+ Validate that all values passed are valid IP addresses,
+ regardless they are IPv4 or IPv6
+ Fail compilation if any value fails this check.
+ The following values will pass:
+ $my_ip = "1.2.3.4"
+ validate_ip_address($my_ip)
+ validate_ip_address("8.8.8.8", "172.16.0.1", $my_ip)
+
+ $my_ip = "3ffe:505:2"
+ validate_ip_address(1)
+ validate_ip_address($my_ip)
+ validate_ip_address("fe80::baf6:b1ff:fe19:7507", $my_ip)
+
+ The following values will fail, causing compilation to abort:
+ $some_array = [ 1, true, false, "garbage string", "3ffe:505:2" ]
+ validate_ip_address($some_array)
+ ENDHEREDOC
+ ) do |args|
+
+ require "ipaddr"
+ rescuable_exceptions = [ ArgumentError ]
+
+ function_deprecation([:validate_ip_address, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ip_address. There is further documentation for validate_legacy function in the README.'])
+
+ if defined?(IPAddr::InvalidAddressError)
+ rescuable_exceptions << IPAddr::InvalidAddressError
+ end
+
+ unless args.length > 0 then
+ raise Puppet::ParseError, ("validate_ip_address(): wrong number of arguments (#{args.length}; must be > 0)")
+ end
+
+ args.each do |arg|
+ unless arg.is_a?(String)
+ raise Puppet::ParseError, "#{arg.inspect} is not a string."
+ end
+
+ begin
+ unless IPAddr.new(arg).ipv4? or IPAddr.new(arg).ipv6?
+ raise Puppet::ParseError, "#{arg.inspect} is not a valid IP address."
+ end
+ rescue *rescuable_exceptions
+ raise Puppet::ParseError, "#{arg.inspect} is not a valid IP address."
+ end
+ end
+
+ end
+
+end
diff --git a/lib/puppet/parser/functions/validate_ipv4_address.rb b/lib/puppet/parser/functions/validate_ipv4_address.rb
index fc02748..0660abd 100644
--- a/lib/puppet/parser/functions/validate_ipv4_address.rb
+++ b/lib/puppet/parser/functions/validate_ipv4_address.rb
@@ -8,7 +8,7 @@ module Puppet::Parser::Functions
$my_ip = "1.2.3.4"
validate_ipv4_address($my_ip)
- validate_bool("8.8.8.8", "172.16.0.1", $my_ip)
+ validate_ipv4_address("8.8.8.8", "172.16.0.1", $my_ip)
The following values will fail, causing compilation to abort:
@@ -18,6 +18,8 @@ module Puppet::Parser::Functions
ENDHEREDOC
) do |args|
+ function_deprecation([:validate_ipv4_address, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ipv4. There is further documentation for validate_legacy function in the README.'])
+
require "ipaddr"
rescuable_exceptions = [ ArgumentError ]
diff --git a/lib/puppet/parser/functions/validate_ipv6_address.rb b/lib/puppet/parser/functions/validate_ipv6_address.rb
index b0f2558..f5dd9e5 100644
--- a/lib/puppet/parser/functions/validate_ipv6_address.rb
+++ b/lib/puppet/parser/functions/validate_ipv6_address.rb
@@ -19,6 +19,8 @@ module Puppet::Parser::Functions
ENDHEREDOC
) do |args|
+ function_deprecation([:validate_ipv6_address, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Ipv6. There is further documentation for validate_legacy function in the README.'])
+
require "ipaddr"
rescuable_exceptions = [ ArgumentError ]
diff --git a/lib/puppet/parser/functions/validate_numeric.rb b/lib/puppet/parser/functions/validate_numeric.rb
new file mode 100644
index 0000000..4205b30
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_numeric.rb
@@ -0,0 +1,96 @@
+module Puppet::Parser::Functions
+
+ newfunction(:validate_numeric, :doc => <<-'ENDHEREDOC') do |args|
+ Validate that the first argument is a numeric value (or an array of numeric values). Abort catalog compilation if any of the checks fail.
+
+ The second argument is optional and passes a maximum. (All elements of) the first argument has to be less or equal to this max.
+
+ The third argument is optional and passes a minimum. (All elements of) the first argument has to be greater or equal to this min.
+ If, and only if, a minimum is given, the second argument may be an empty string or undef, which will be handled to just check
+ if (all elements of) the first argument are greater or equal to the given minimum.
+
+ It will fail if the first argument is not a numeric (Integer or Float) or array of numerics, and if arg 2 and arg 3 are not convertable to a numeric.
+
+ For passing and failing usage, see `validate_integer()`. It is all the same for validate_numeric, yet now floating point values are allowed, too.
+
+ ENDHEREDOC
+
+ function_deprecation([:validate_numeric, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Numeric. There is further documentation for validate_legacy function in the README.'])
+
+ # tell the user we need at least one, and optionally up to two other parameters
+ raise Puppet::ParseError, "validate_numeric(): Wrong number of arguments; must be 1, 2 or 3, got #{args.length}" unless args.length > 0 and args.length < 4
+
+ input, max, min = *args
+
+ # check maximum parameter
+ if args.length > 1
+ max = max.to_s
+ # allow max to be empty (or undefined) if we have a minimum set
+ if args.length > 2 and max == ''
+ max = nil
+ else
+ begin
+ max = Float(max)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_numeric(): Expected second argument to be unset or a Numeric, got #{max}:#{max.class}"
+ end
+ end
+ else
+ max = nil
+ end
+
+ # check minimum parameter
+ if args.length > 2
+ begin
+ min = Float(min.to_s)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_numeric(): Expected third argument to be unset or a Numeric, got #{min}:#{min.class}"
+ end
+ else
+ min = nil
+ end
+
+ # ensure that min < max
+ if min and max and min > max
+ raise Puppet::ParseError, "validate_numeric(): Expected second argument to be larger than third argument, got #{max} < #{min}"
+ end
+
+ # create lamba validator function
+ validator = lambda do |num|
+ # check input < max
+ if max and num > max
+ raise Puppet::ParseError, "validate_numeric(): Expected #{input.inspect} to be smaller or equal to #{max}, got #{input.inspect}."
+ end
+ # check input > min (this will only be checked if no exception has been raised before)
+ if min and num < min
+ raise Puppet::ParseError, "validate_numeric(): Expected #{input.inspect} to be greater or equal to #{min}, got #{input.inspect}."
+ end
+ end
+
+ # if this is an array, handle it.
+ case input
+ when Array
+ # check every element of the array
+ input.each_with_index do |arg, pos|
+ begin
+ raise TypeError if arg.is_a?(Hash)
+ arg = Float(arg.to_s)
+ validator.call(arg)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_numeric(): Expected element at array position #{pos} to be a Numeric, got #{arg.class}"
+ end
+ end
+ # for the sake of compatibility with ruby 1.8, we need extra handling of hashes
+ when Hash
+ raise Puppet::ParseError, "validate_integer(): Expected first argument to be a Numeric or Array, got #{input.class}"
+ # check the input. this will also fail any stuff other than pure, shiny integers
+ else
+ begin
+ input = Float(input.to_s)
+ validator.call(input)
+ rescue TypeError, ArgumentError
+ raise Puppet::ParseError, "validate_numeric(): Expected first argument to be a Numeric or Array, got #{input.class}"
+ end
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/validate_re.rb b/lib/puppet/parser/functions/validate_re.rb
index ca25a70..0ac83dd 100644
--- a/lib/puppet/parser/functions/validate_re.rb
+++ b/lib/puppet/parser/functions/validate_re.rb
@@ -23,16 +23,26 @@ module Puppet::Parser::Functions
validate_re($::puppetversion, '^2.7', 'The $puppetversion fact value does not match 2.7')
+ Note: Compilation will also abort, if the first argument is not a String. Always use
+ quotes to force stringification:
+
+ validate_re("${::operatingsystemmajrelease}", '^[57]$')
+
ENDHEREDOC
+
+ function_deprecation([:validate_re, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::Re. There is further documentation for validate_legacy function in the README.'])
+
if (args.length < 2) or (args.length > 3) then
- raise Puppet::ParseError, ("validate_re(): wrong number of arguments (#{args.length}; must be 2 or 3)")
+ raise Puppet::ParseError, "validate_re(): wrong number of arguments (#{args.length}; must be 2 or 3)"
end
+ raise Puppet::ParseError, "validate_re(): input needs to be a String, not a #{args[0].class}" unless args[0].is_a? String
+
msg = args[2] || "validate_re(): #{args[0].inspect} does not match #{args[1].inspect}"
# We're using a flattened array here because we can't call String#any? in
# Ruby 1.9 like we can in Ruby 1.8
- raise Puppet::ParseError, (msg) unless [args[1]].flatten.any? do |re_str|
+ raise Puppet::ParseError, msg unless [args[1]].flatten.any? do |re_str|
args[0] =~ Regexp.compile(re_str)
end
diff --git a/lib/puppet/parser/functions/validate_slength.rb b/lib/puppet/parser/functions/validate_slength.rb
index 7d534f3..383855c 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.
@@ -21,6 +21,8 @@ module Puppet::Parser::Functions
ENDHEREDOC
+ function_deprecation([:validate_slength, 'This method is deprecated, please use the stdlib validate_legacy function, with String[]. There is further documentation for validate_legacy function in the README.'])
+
raise Puppet::ParseError, "validate_slength(): Wrong number of arguments (#{args.length}; must be 2 or 3)" unless args.length == 2 or args.length == 3
input, max_length, min_length = *args
@@ -43,9 +45,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/parser/functions/validate_string.rb b/lib/puppet/parser/functions/validate_string.rb
index c841f6a..6675d86 100644
--- a/lib/puppet/parser/functions/validate_string.rb
+++ b/lib/puppet/parser/functions/validate_string.rb
@@ -13,22 +13,25 @@ module Puppet::Parser::Functions
validate_string(true)
validate_string([ 'some', 'array' ])
-
+
Note: validate_string(undef) will not fail in this version of the
functions API (incl. current and future parser). Instead, use:
-
+
if $var == undef {
fail('...')
}
-
+
ENDHEREDOC
+ function_deprecation([:validate_string, 'This method is deprecated, please use the stdlib validate_legacy function, with Stdlib::Compat::String. There is further documentation for validate_legacy function in the README.'])
+
unless args.length > 0 then
raise Puppet::ParseError, ("validate_string(): wrong number of arguments (#{args.length}; must be > 0)")
end
args.each do |arg|
- unless arg.is_a?(String)
+ # when called through the v4 API shim, undef gets translated to nil
+ unless arg.is_a?(String) || arg.nil?
raise Puppet::ParseError, ("#{arg.inspect} is not a string. It looks to be a #{arg.class}")
end
end
diff --git a/lib/puppet/parser/functions/validate_x509_rsa_key_pair.rb b/lib/puppet/parser/functions/validate_x509_rsa_key_pair.rb
new file mode 100644
index 0000000..fc9f23f
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_x509_rsa_key_pair.rb
@@ -0,0 +1,47 @@
+module Puppet::Parser::Functions
+
+ newfunction(:validate_x509_rsa_key_pair, :doc => <<-ENDHEREDOC
+ Validates a PEM-formatted X.509 certificate and RSA private key using
+ OpenSSL. Verifies that the certficate's signature was created from the
+ supplied key.
+
+ Fail compilation if any value fails this check.
+
+ validate_x509_rsa_key_pair($cert, $key)
+
+ ENDHEREDOC
+ ) do |args|
+
+ require 'openssl'
+
+ NUM_ARGS = 2 unless defined? NUM_ARGS
+
+ unless args.length == NUM_ARGS then
+ raise Puppet::ParseError,
+ ("validate_x509_rsa_key_pair(): wrong number of arguments (#{args.length}; must be #{NUM_ARGS})")
+ end
+
+ args.each do |arg|
+ unless arg.is_a?(String)
+ raise Puppet::ParseError, "#{arg.inspect} is not a string."
+ end
+ end
+
+ begin
+ cert = OpenSSL::X509::Certificate.new(args[0])
+ rescue OpenSSL::X509::CertificateError => e
+ raise Puppet::ParseError, "Not a valid x509 certificate: #{e}"
+ end
+
+ begin
+ key = OpenSSL::PKey::RSA.new(args[1])
+ rescue OpenSSL::PKey::RSAError => e
+ raise Puppet::ParseError, "Not a valid RSA key: #{e}"
+ end
+
+ unless cert.verify(key)
+ raise Puppet::ParseError, "Certificate signature does not match supplied key"
+ end
+ end
+
+end
diff --git a/lib/puppet/provider/file_line/ruby.rb b/lib/puppet/provider/file_line/ruby.rb
index ae1a8b3..beeb430 100644
--- a/lib/puppet/provider/file_line/ruby.rb
+++ b/lib/puppet/provider/file_line/ruby.rb
@@ -1,24 +1,35 @@
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|
+ if resource[:ensure].to_s == 'absent' and resource[:match_for_absence].to_s == 'true'
+ line.chomp =~ Regexp.new(resource[:match])
+ else
+ line.chomp == resource[:line].chomp
+ end
+ 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,15 +43,27 @@ 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
- match_count = count_matches(regex)
+ regex_after = resource[:after] ? Regexp.new(resource[:after]) : nil
+ 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
+
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])
+ match_count += 1 #Increment match_count to indicate that the new line has been inserted.
+ end
+ end
end
if (match_count == 0)
@@ -52,20 +75,22 @@ Puppet::Type.type(:file_line).provide(:ruby) do
def handle_create_with_after
regex = Regexp.new(resource[:after])
count = count_matches(regex)
- case count
- when 1 # find the line to put our line after
- File.open(resource[:path], 'w') do |fh|
- lines.each do |l|
- fh.puts(l)
- if regex.match(l) then
- fh.puts(resource[:line])
- end
+
+ if count > 1 && resource[:multiple].to_s != 'true'
+ raise Puppet::Error, "#{count} lines match pattern '#{resource[:after]}' in file '#{resource[:path]}'. One or no line must match the pattern."
+ end
+
+ File.open(resource[:path], 'w') do |fh|
+ lines.each do |l|
+ fh.puts(l)
+ if regex.match(l) then
+ fh.puts(resource[:line])
end
end
- when 0 # append the line to the end of the file
+ end
+
+ if (count == 0) # append the line to the end of the file
append_line
- else
- raise Puppet::Error, "#{count} lines match pattern '#{resource[:after]}' in file '#{resource[:path]}'. One or no line must match the pattern."
end
end
@@ -73,12 +98,34 @@ 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.
#
# @api private
def append_line
- File.open(resource[:path], 'a') do |fh|
+ File.open(resource[:path], 'w') do |fh|
+ lines.each do |l|
+ fh.puts(l)
+ end
fh.puts resource[:line]
end
end
diff --git a/lib/puppet/type/file_line.rb b/lib/puppet/type/file_line.rb
index df263e6..7b7d44e 100644
--- a/lib/puppet/type/file_line.rb
+++ b/lib/puppet/type/file_line.rb
@@ -3,9 +3,9 @@ Puppet::Type.newtype(:file_line) do
desc <<-EOT
Ensures that a given line is contained within a file. The implementation
matches the full line, including whitespace at the beginning and end. If
- the line is not contained in the given file, Puppet will add the line to
- ensure the desired state. Multiple resources may be declared to manage
- multiple lines in the same file.
+ the line is not contained in the given file, Puppet will append the line to
+ the end of the file to ensure the desired state. Multiple resources may
+ be declared to manage multiple lines in the same file.
Example:
@@ -13,6 +13,7 @@ Puppet::Type.newtype(:file_line) do
path => '/etc/sudoers',
line => '%sudo ALL=(ALL) ALL',
}
+
file_line { 'sudo_rule_nopw':
path => '/etc/sudoers',
line => '%sudonopw ALL=(ALL) NOPASSWD: ALL',
@@ -21,9 +22,34 @@ Puppet::Type.newtype(:file_line) do
In this example, Puppet will ensure both of the specified lines are
contained in the file /etc/sudoers.
+ Match Example:
+
+ file_line { 'bashrc_proxy':
+ ensure => present,
+ path => '/etc/bashrc',
+ line => 'export HTTP_PROXY=http://squid.puppetlabs.vm:3128',
+ match => '^export\ HTTP_PROXY\=',
+ }
+
+ 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.
-
EOT
ensurable do
@@ -36,40 +62,64 @@ Puppet::Type.newtype(:file_line) do
end
newparam(:match) do
- desc 'An optional regular expression to run against existing lines in the file;\n' +
- 'if a match is found, we replace that line rather than adding a new line.'
+ desc 'An optional ruby regular expression to run against existing lines in the file.' +
+ ' If a match is found, we replace that line rather than adding a new line.' +
+ ' A regex comparison is performed against the line value and if it does not' +
+ ' 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.' +
+ ' When `ensure => present`, match_for_absence is ignored.'
+ newvalues(true, false)
+ defaultto false
end
newparam(:multiple) do
- desc 'An optional value to determine if match can change multiple lines.'
+ 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'
newvalues(true, false)
end
newparam(:after) do
- desc 'An optional value used to specify the line after which we will add any new lines. (Existing lines are added in place)'
+ desc 'An optional value used to specify the line after which we will add any new lines. (Existing lines are added in place)' +
+ ' This is also takes a regex.'
end
newparam(:line) do
- desc 'The line to be appended to the file located by the path parameter.'
+ desc 'The line to be appended to the file or used to replace matches found by the match attribute.'
end
newparam(:path) do
desc 'The file Puppet will ensure contains the line specified by the line parameter.'
validate do |value|
- unless (Puppet.features.posix? and value =~ /^\//) or (Puppet.features.microsoft_windows? and (value =~ /^.:\// or value =~ /^\/\/[^\/]+\/[^\/]+/))
- raise(Puppet::Error, "File paths must be fully qualified, not '#{value}'")
+ unless Puppet::Util.absolute_path?(value)
+ raise Puppet::Error, "File paths must be fully qualified, not '#{value}'"
end
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]
end
validate do
- unless self[:line] and self[:path]
- raise(Puppet::Error, "Both line and path are required attributes")
+ unless self[:line]
+ unless (self[:ensure].to_s == 'absent') and (self[:match_for_absence].to_s == 'true') and self[:match]
+ raise(Puppet::Error, "line is a required attribute")
+ end
+ end
+ unless self[:path]
+ raise(Puppet::Error, "path is a required attribute")
end
end
end
diff --git a/manifests/init.pp b/manifests/init.pp
index 500ad77..9ea22a7 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -14,7 +14,5 @@
# Requires: nothing
#
class stdlib {
-
- class { 'stdlib::stages': }
-
+ include ::stdlib::stages
}
diff --git a/manifests/stages.pp b/manifests/stages.pp
index eb15fd6..7de254c 100644
--- a/manifests/stages.pp
+++ b/manifests/stages.pp
@@ -26,7 +26,7 @@
# Sample Usage:
#
# node default {
-# include stdlib
+# include ::stdlib
# class { java: stage => 'runtime' }
# }
#
diff --git a/metadata.json b/metadata.json
index 27def9c..82078bf 100644
--- a/metadata.json
+++ b/metadata.json
@@ -1,6 +1,6 @@
{
"name": "puppetlabs-stdlib",
- "version": "4.5.1",
+ "version": "4.13.1",
"author": "puppetlabs",
"summary": "Standard library of resources for Puppet modules.",
"license": "Apache-2.0",
@@ -56,7 +56,8 @@
"operatingsystem": "Debian",
"operatingsystemrelease": [
"6",
- "7"
+ "7",
+ "8"
]
},
{
@@ -64,14 +65,16 @@
"operatingsystemrelease": [
"10.04",
"12.04",
- "14.04"
+ "14.04",
+ "16.06"
]
},
{
"operatingsystem": "Solaris",
"operatingsystemrelease": [
"10",
- "11"
+ "11",
+ "12"
]
},
{
@@ -98,16 +101,12 @@
],
"requirements": [
{
- "name": "pe",
- "version_requirement": "3.x"
- },
- {
"name": "puppet",
- "version_requirement": ">=2.7.20 <4.0.0"
+ "version_requirement": ">=2.7.20 <5.0.0"
}
],
"description": "Standard Library for Puppet Modules",
"dependencies": [
-
+
]
}
diff --git a/spec/acceptance/anchor_spec.rb b/spec/acceptance/anchor_spec.rb
new file mode 100755
index 0000000..5bc2bbb
--- /dev/null
+++ b/spec/acceptance/anchor_spec.rb
@@ -0,0 +1,26 @@
+require 'spec_helper_acceptance'
+
+describe 'anchor type', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+ describe 'success' do
+ it 'should effect proper chaining of resources' do
+ pp = <<-EOS
+ class anchored {
+ anchor { 'anchored::begin': }
+ ~> anchor { 'anchored::end': }
+ }
+
+ class anchorrefresh {
+ notify { 'first': }
+ ~> class { 'anchored': }
+ ~> anchor { 'final': }
+ }
+
+ include anchorrefresh
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/Anchor\[final\]: Triggered 'refresh'/)
+ end
+ end
+ end
+end
diff --git a/spec/acceptance/ceiling_spec.rb b/spec/acceptance/ceiling_spec.rb
new file mode 100755
index 0000000..557986e
--- /dev/null
+++ b/spec/acceptance/ceiling_spec.rb
@@ -0,0 +1,39 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'ceiling function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+ describe 'success' do
+ it 'ceilings floats' do
+ pp = <<-EOS
+ $a = 12.8
+ $b = 13
+ $o = ceiling($a)
+ if $o == $b {
+ notify { 'output correct': }
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/Notice: output correct/)
+ end
+ end
+ it 'ceilings integers' do
+ pp = <<-EOS
+ $a = 7
+ $b = 7
+ $o = ceiling($a)
+ if $o == $b {
+ notify { 'output correct': }
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/Notice: output correct/)
+ end
+ end
+ end
+ describe 'failure' do
+ it 'handles improper argument counts'
+ it 'handles non-numbers'
+ end
+end
diff --git a/spec/acceptance/clamp_spec.rb b/spec/acceptance/clamp_spec.rb
new file mode 100755
index 0000000..0189258
--- /dev/null
+++ b/spec/acceptance/clamp_spec.rb
@@ -0,0 +1,40 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'clamp function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+ describe 'success' do
+ it 'clamps list of values' do
+ pp = <<-EOS
+ $x = 17
+ $y = 225
+ $z = 155
+ $o = clamp($x, $y, $z)
+ if $o == $z {
+ notify { 'output correct': }
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/Notice: output correct/)
+ end
+ end
+ it 'clamps array of values' do
+ pp = <<-EOS
+ $a = [7, 19, 66]
+ $b = 19
+ $o = clamp($a)
+ if $o == $b {
+ notify { 'output correct': }
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/Notice: output correct/)
+ end
+ end
+ end
+ describe 'failure' do
+ it 'handles improper argument counts'
+ it 'handles no arguments'
+ end
+end
diff --git a/spec/acceptance/concat_spec.rb b/spec/acceptance/concat_spec.rb
index 06b649f..c472db6 100755
--- a/spec/acceptance/concat_spec.rb
+++ b/spec/acceptance/concat_spec.rb
@@ -36,5 +36,19 @@ describe 'concat function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('oper
apply_manifest(pp, :catch_failures => true)
end
+ it 'should concat hash arguments' do
+ pp = <<-EOS
+ $output = concat([{"a" => "b"}], {"c" => "d", "e" => "f"})
+ validate_array($output)
+ if size($output) != 2 {
+ fail("${output} should have 2 elements.")
+ }
+ if $output[1] != {"c" => "d", "e" => "f"} {
+ fail("${output} does not have the expected hash for the second element.")
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true)
+ end
end
end
diff --git a/spec/acceptance/deprecation_spec.rb b/spec/acceptance/deprecation_spec.rb
new file mode 100644
index 0000000..7a0b34c
--- /dev/null
+++ b/spec/acceptance/deprecation_spec.rb
@@ -0,0 +1,102 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'deprecation function' do
+
+ if fact('operatingsystem') == 'windows'
+ test_file = 'C:/deprecation'
+ else
+ test_file = "/tmp/deprecation"
+ end
+
+ # It seems that Windows needs everything to be on one line when using puppet apply -e, otherwise the manifests would be in an easier format
+ add_file_manifest = "\"deprecation('key', 'message') file { '#{test_file}': ensure => present, content => 'test', }\""
+ remove_file_manifest = "file { '#{test_file}': ensure => absent }"
+
+ before :all do
+ apply_manifest(remove_file_manifest)
+ end
+
+ context 'with --strict=error', if: get_puppet_version =~ /^4/ do
+ before :all do
+ @result = on(default, puppet('apply', '--strict=error', '-e', add_file_manifest), acceptable_exit_codes: (0...256))
+ end
+
+ after :all do
+ apply_manifest(remove_file_manifest)
+ end
+
+ it "should return an error" do
+ expect(@result.exit_code).to eq(1)
+ end
+
+ it "should show the error message" do
+ expect(@result.stderr).to match(/deprecation. key. message/)
+ end
+
+ describe file("#{test_file}") do
+ it { is_expected.not_to be_file }
+ end
+ end
+
+ context 'with --strict=warning', if: get_puppet_version =~ /^4/ do
+ before :all do
+ @result = on(default, puppet('apply', '--strict=warning', '-e', add_file_manifest), acceptable_exit_codes: (0...256))
+ end
+
+ after :all do
+ apply_manifest(remove_file_manifest)
+ end
+
+ it "should not return an error" do
+ expect(@result.exit_code).to eq(0)
+ end
+
+ it "should show the error message" do
+ expect(@result.stderr).to match(/Warning: message/)
+ end
+
+ describe file("#{test_file}") do
+ it { is_expected.to be_file }
+ end
+ end
+
+ context 'with --strict=off', if: get_puppet_version =~ /^4/ do
+ before :all do
+ @result = on(default, puppet('apply', '--strict=off', '-e', add_file_manifest), acceptable_exit_codes: (0...256))
+ end
+
+ after :all do
+ apply_manifest(remove_file_manifest)
+ end
+
+ it "should not return an error" do
+ expect(@result.exit_code).to eq(0)
+ end
+
+ it "should not show the error message" do
+ expect(@result.stderr).not_to match(/Warning: message/)
+ end
+
+ describe file("#{test_file}") do
+ it { is_expected.to be_file }
+ end
+ end
+
+ context 'puppet 3 test', if: get_puppet_version =~ /^3/ do
+ before :all do
+ @result = on(default, puppet('apply', '--parser=future', '-e', add_file_manifest), acceptable_exit_codes: (0...256))
+ end
+ after :all do
+ apply_manifest(remove_file_manifest)
+ end
+
+ it "should return a deprecation error" do
+ expect(@result.stderr).to match(/Warning: message/)
+ end
+ it "should pass without error" do
+ expect(@result.exit_code).to eq(0)
+ end
+ end
+
+end
diff --git a/spec/acceptance/empty_spec.rb b/spec/acceptance/empty_spec.rb
index 8b46aac..2d4df90 100755
--- a/spec/acceptance/empty_spec.rb
+++ b/spec/acceptance/empty_spec.rb
@@ -31,6 +31,20 @@ describe 'empty function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('opera
expect(r.stdout).to match(/Notice: output correct/)
end
end
+ it 'handles numerical values' do
+ pp = <<-EOS
+ $a = 7
+ $b = false
+ $o = empty($a)
+ if $o == $b {
+ notify { 'output correct': }
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/Notice: output correct/)
+ end
+ end
end
describe 'failure' do
it 'handles improper argument counts'
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..93f25dd 100755
--- a/spec/acceptance/ensure_resource_spec.rb
+++ b/spec/acceptance/ensure_resource_spec.rb
@@ -1,18 +1,26 @@
#! /usr/bin/env ruby -S rspec
require 'spec_helper_acceptance'
-describe 'ensure_resource function', :unless => fact('osfamily') =~ /windows/i do
+describe 'ensure_resource function' do
describe 'success' do
- it 'ensure_resource a package' do
- apply_manifest('package { "rake": ensure => absent, provider => "gem", }')
+ it 'ensures a resource already declared' do
+ apply_manifest('')
pp = <<-EOS
- $a = "rake"
- ensure_resource('package', $a, {'provider' => 'gem'})
+ notify { "test": loglevel => 'err' }
+ ensure_resource('notify', 'test', { 'loglevel' => 'err' })
+ EOS
+
+ apply_manifest(pp, :expect_changes => true)
+ end
+
+ it 'ensures a undeclared resource' do
+ apply_manifest('')
+ pp = <<-EOS
+ ensure_resource('notify', 'test', { 'loglevel' => 'err' })
EOS
apply_manifest(pp, :expect_changes => true)
end
- it 'ensures a resource already declared'
it 'takes defaults arguments'
end
describe 'failure' do
diff --git a/spec/acceptance/fqdn_rand_string_spec.rb b/spec/acceptance/fqdn_rand_string_spec.rb
new file mode 100644
index 0000000..065a517
--- /dev/null
+++ b/spec/acceptance/fqdn_rand_string_spec.rb
@@ -0,0 +1,66 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'fqdn_rand_string function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+ describe 'success' do
+ include_context "with faked facts"
+ context "when the FQDN is 'fakehost.localdomain'" do
+ before :each do
+ fake_fact("fqdn", "fakehost.localdomain")
+ end
+
+ 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|9Acvnhkt4J)"/)
+ end
+ end
+ 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|2383756694)"/)
+ end
+ end
+ 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|1jJtAMs94d)"/)
+ end
+ end
+ 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|7100592312)"/)
+ end
+ end
+ end
+ end
+ describe 'failure' do
+ it 'handles improper argument counts'
+ it 'handles non-numbers for length argument'
+ end
+end
diff --git a/spec/acceptance/fqdn_rotate_spec.rb b/spec/acceptance/fqdn_rotate_spec.rb
index 753068b..404351f 100755
--- a/spec/acceptance/fqdn_rotate_spec.rb
+++ b/spec/acceptance/fqdn_rotate_spec.rb
@@ -3,45 +3,62 @@ 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'
+ include_context "with faked facts"
+ context "when the FQDN is 'fakehost.localdomain'" do
+ before :each do
+ fake_fact("fqdn", "fakehost.localdomain")
+ end
+
+ 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
- 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}'")
+ 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"\]/)
+ end
end
- end
- it 'fqdn_rotates floats' 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
+ 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"/)
+ end
+ end
+ 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 \["c", "d", "a", "b"\]/)
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/fqdn_rotate is "cdab"/)
+ end
end
end
end
describe 'failure' do
it 'handles improper argument counts'
- it 'handles non-numbers'
+ it 'handles invalid arguments'
end
end
diff --git a/spec/acceptance/is_a_spec.rb b/spec/acceptance/is_a_spec.rb
new file mode 100644
index 0000000..355fd83
--- /dev/null
+++ b/spec/acceptance/is_a_spec.rb
@@ -0,0 +1,30 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+if get_puppet_version =~ /^4/
+ describe 'is_a function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+ it 'should match a string' do
+ pp = <<-EOS
+ if 'hello world'.is_a(String) {
+ notify { 'output correct': }
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/Notice: output correct/)
+ end
+ end
+
+ it 'should not match a integer as string' do
+ pp = <<-EOS
+ if 5.is_a(String) {
+ notify { 'output wrong': }
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).not_to match(/Notice: output wrong/)
+ end
+ end
+ end
+end
diff --git a/spec/acceptance/is_ipv4_address_spec.rb b/spec/acceptance/is_ipv4_address_spec.rb
new file mode 100755
index 0000000..5dc6bf5
--- /dev/null
+++ b/spec/acceptance/is_ipv4_address_spec.rb
@@ -0,0 +1,52 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'is_ipv4_address function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+ describe 'success' do
+ it 'is_ipv4_addresss' do
+ pp = <<-EOS
+ $a = '1.2.3.4'
+ $b = true
+ $o = is_ipv4_address($a)
+ if $o == $b {
+ notify { 'output correct': }
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/Notice: output correct/)
+ end
+ end
+ it 'is_ipv4_addresss strings' do
+ pp = <<-EOS
+ $a = "aoeu"
+ $b = false
+ $o = is_ipv4_address($a)
+ if $o == $b {
+ notify { 'output correct': }
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/Notice: output correct/)
+ end
+ end
+ it 'is_ipv4_addresss ipv4 out of range' do
+ pp = <<-EOS
+ $a = '1.2.3.400'
+ $b = false
+ $o = is_ipv4_address($a)
+ if $o == $b {
+ notify { 'output correct': }
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/Notice: output correct/)
+ end
+ end
+ end
+ describe 'failure' do
+ it 'handles improper argument counts'
+ end
+end
diff --git a/spec/acceptance/is_ipv6_address_spec.rb b/spec/acceptance/is_ipv6_address_spec.rb
new file mode 100755
index 0000000..1e88be8
--- /dev/null
+++ b/spec/acceptance/is_ipv6_address_spec.rb
@@ -0,0 +1,66 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'is_ipv6_address function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+ describe 'success' do
+ it 'is_ipv6_addresss' do
+ pp = <<-EOS
+ $a = "fe80:0000:cd12:d123:e2f8:47ff:fe09:dd74"
+ $b = true
+ $o = is_ipv6_address($a)
+ if $o == $b {
+ notify { 'output correct': }
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/Notice: output correct/)
+ end
+ end
+ it 'is_ipv6_addresss ipv6 compressed' do
+ pp = <<-EOS
+ $a = "fe00::1"
+ $b = true
+ $o = is_ipv6_address($a)
+ if $o == $b {
+ notify { 'output correct': }
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/Notice: output correct/)
+ end
+ end
+ it 'is_ipv6_addresss strings' do
+ pp = <<-EOS
+ $a = "aoeu"
+ $b = false
+ $o = is_ipv6_address($a)
+ if $o == $b {
+ notify { 'output correct': }
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/Notice: output correct/)
+ end
+ end
+ it 'is_ipv6_addresss ip out of range' do
+ pp = <<-EOS
+ $a = 'fe80:0000:cd12:d123:e2f8:47ff:fe09:gggg'
+ $b = false
+ $o = is_ipv6_address($a)
+ if $o == $b {
+ notify { 'output correct': }
+ }
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/Notice: output correct/)
+ end
+ end
+ end
+ describe 'failure' do
+ it 'handles improper argument counts'
+ end
+end
diff --git a/spec/acceptance/is_string_spec.rb b/spec/acceptance/is_string_spec.rb
index 94d8e96..f526888 100755
--- a/spec/acceptance/is_string_spec.rb
+++ b/spec/acceptance/is_string_spec.rb
@@ -95,6 +95,17 @@ describe 'is_string function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('o
expect(r.stdout).to match(/Notice: output correct/)
end
end
+ it 'is_strings undef' do
+ pp = <<-EOS
+ $a = undef
+ $o = is_string($a)
+ notice(inline_template('is_string is <%= @o.inspect %>'))
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/is_string is true/)
+ end
+ end
end
describe 'failure' do
it 'handles improper argument counts'
diff --git a/spec/acceptance/loadjson_spec.rb b/spec/acceptance/loadjson_spec.rb
new file mode 100644
index 0000000..2992c37
--- /dev/null
+++ b/spec/acceptance/loadjson_spec.rb
@@ -0,0 +1,52 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+tmpdir = default.tmpdir('stdlib')
+
+describe 'loadjson function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+ describe 'success' do
+ it 'loadjsons array of values' do
+ shell("echo '{\"aaa\":1,\"bbb\":2,\"ccc\":3,\"ddd\":4}' > #{tmpdir}/testjson.json")
+ pp = <<-EOS
+ $o = loadjson('#{tmpdir}/testjson.json')
+ notice(inline_template('loadjson[aaa] is <%= @o["aaa"].inspect %>'))
+ notice(inline_template('loadjson[bbb] is <%= @o["bbb"].inspect %>'))
+ notice(inline_template('loadjson[ccc] is <%= @o["ccc"].inspect %>'))
+ notice(inline_template('loadjson[ddd] is <%= @o["ddd"].inspect %>'))
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/loadjson\[aaa\] is 1/)
+ expect(r.stdout).to match(/loadjson\[bbb\] is 2/)
+ expect(r.stdout).to match(/loadjson\[ccc\] is 3/)
+ expect(r.stdout).to match(/loadjson\[ddd\] is 4/)
+ end
+ end
+
+ it 'returns the default value if there is no file to load' do
+ pp = <<-EOS
+ $o = loadjson('#{tmpdir}/no-file.json', {'default' => 'value'})
+ notice(inline_template('loadjson[default] is <%= @o["default"].inspect %>'))
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/loadjson\[default\] is "value"/)
+ end
+ end
+
+ it 'returns the default value if the file was parsed with an error' do
+ shell("echo '!' > #{tmpdir}/testjson.json")
+ pp = <<-EOS
+ $o = loadjson('#{tmpdir}/testjson.json', {'default' => 'value'})
+ notice(inline_template('loadjson[default] is <%= @o["default"].inspect %>'))
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/loadjson\[default\] is "value"/)
+ end
+ end
+ end
+ describe 'failure' do
+ it 'fails with no arguments'
+ end
+end
diff --git a/spec/acceptance/loadyaml_spec.rb b/spec/acceptance/loadyaml_spec.rb
index 1e910a9..ba3f0b7 100644
--- a/spec/acceptance/loadyaml_spec.rb
+++ b/spec/acceptance/loadyaml_spec.rb
@@ -26,6 +26,29 @@ describe 'loadyaml function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('op
expect(r.stdout).to match(/loadyaml\[ddd\] is 4/)
end
end
+
+ it 'returns the default value if there is no file to load' do
+ pp = <<-EOS
+ $o = loadyaml('#{tmpdir}/no-file.yaml', {'default' => 'value'})
+ notice(inline_template('loadyaml[default] is <%= @o["default"].inspect %>'))
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/loadyaml\[default\] is "value"/)
+ end
+ end
+
+ it 'returns the default value if the file was parsed with an error' do
+ shell("echo '!' > #{tmpdir}/testyaml.yaml")
+ pp = <<-EOS
+ $o = loadyaml('#{tmpdir}/testyaml.yaml', {'default' => 'value'})
+ notice(inline_template('loadyaml[default] is <%= @o["default"].inspect %>'))
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/loadyaml\[default\] is "value"/)
+ end
+ end
end
describe 'failure' do
it 'fails with no arguments'
diff --git a/spec/acceptance/nodesets/centos-59-x64.yml b/spec/acceptance/nodesets/centos-59-x64.yml
deleted file mode 100644
index 2ad90b8..0000000
--- a/spec/acceptance/nodesets/centos-59-x64.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-HOSTS:
- centos-59-x64:
- roles:
- - master
- platform: el-5-x86_64
- box : centos-59-x64-vbox4210-nocm
- box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-59-x64-vbox4210-nocm.box
- hypervisor : vagrant
-CONFIG:
- type: git
diff --git a/spec/acceptance/nodesets/centos-6-vcloud.yml b/spec/acceptance/nodesets/centos-6-vcloud.yml
deleted file mode 100644
index ca9c1d3..0000000
--- a/spec/acceptance/nodesets/centos-6-vcloud.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-HOSTS:
- 'centos-6-vcloud':
- roles:
- - master
- platform: el-6-x86_64
- hypervisor: vcloud
- template: centos-6-x86_64
-CONFIG:
- type: foss
- ssh:
- keys: "~/.ssh/id_rsa-acceptance"
- datastore: instance0
- folder: Delivery/Quality Assurance/Enterprise/Dynamic
- resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
- pooling_api: http://vcloud.delivery.puppetlabs.net/
diff --git a/spec/acceptance/nodesets/centos-64-x64-pe.yml b/spec/acceptance/nodesets/centos-64-x64-pe.yml
deleted file mode 100644
index 7d9242f..0000000
--- a/spec/acceptance/nodesets/centos-64-x64-pe.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-HOSTS:
- centos-64-x64:
- roles:
- - master
- - database
- - dashboard
- platform: el-6-x86_64
- box : centos-64-x64-vbox4210-nocm
- box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
- hypervisor : vagrant
-CONFIG:
- type: pe
diff --git a/spec/acceptance/nodesets/centos-64-x64.yml b/spec/acceptance/nodesets/centos-64-x64.yml
deleted file mode 100644
index 05540ed..0000000
--- a/spec/acceptance/nodesets/centos-64-x64.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-HOSTS:
- centos-64-x64:
- roles:
- - master
- platform: el-6-x86_64
- box : centos-64-x64-vbox4210-nocm
- box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
- hypervisor : vagrant
-CONFIG:
- type: foss
diff --git a/spec/acceptance/nodesets/centos-65-x64.yml b/spec/acceptance/nodesets/centos-65-x64.yml
deleted file mode 100644
index 4e2cb80..0000000
--- a/spec/acceptance/nodesets/centos-65-x64.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-HOSTS:
- centos-65-x64:
- roles:
- - master
- platform: el-6-x86_64
- box : centos-65-x64-vbox436-nocm
- box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box
- hypervisor : vagrant
-CONFIG:
- type: foss
diff --git a/spec/acceptance/nodesets/centos-7-x64.yml b/spec/acceptance/nodesets/centos-7-x64.yml
new file mode 100644
index 0000000..5eebdef
--- /dev/null
+++ b/spec/acceptance/nodesets/centos-7-x64.yml
@@ -0,0 +1,10 @@
+HOSTS:
+ centos-7-x64:
+ roles:
+ - agent
+ - default
+ platform: el-7-x86_64
+ hypervisor: vagrant
+ box: puppetlabs/centos-7.2-64-nocm
+CONFIG:
+ type: foss
diff --git a/spec/acceptance/nodesets/debian-8-x64.yml b/spec/acceptance/nodesets/debian-8-x64.yml
new file mode 100644
index 0000000..fef6e63
--- /dev/null
+++ b/spec/acceptance/nodesets/debian-8-x64.yml
@@ -0,0 +1,10 @@
+HOSTS:
+ debian-8-x64:
+ roles:
+ - agent
+ - default
+ platform: debian-8-amd64
+ hypervisor: vagrant
+ box: puppetlabs/debian-8.2-64-nocm
+CONFIG:
+ type: foss
diff --git a/spec/acceptance/nodesets/default.yml b/spec/acceptance/nodesets/default.yml
index 4e2cb80..dba339c 100644
--- a/spec/acceptance/nodesets/default.yml
+++ b/spec/acceptance/nodesets/default.yml
@@ -1,10 +1,10 @@
HOSTS:
- centos-65-x64:
+ ubuntu-1404-x64:
roles:
- - master
- platform: el-6-x86_64
- box : centos-65-x64-vbox436-nocm
- box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box
- hypervisor : vagrant
+ - agent
+ - default
+ platform: ubuntu-14.04-amd64
+ hypervisor: vagrant
+ box: puppetlabs/ubuntu-14.04-64-nocm
CONFIG:
type: foss
diff --git a/spec/acceptance/nodesets/docker/centos-7.yml b/spec/acceptance/nodesets/docker/centos-7.yml
new file mode 100644
index 0000000..a3333aa
--- /dev/null
+++ b/spec/acceptance/nodesets/docker/centos-7.yml
@@ -0,0 +1,12 @@
+HOSTS:
+ centos-7-x64:
+ platform: el-7-x86_64
+ hypervisor: docker
+ image: centos:7
+ docker_preserve_image: true
+ docker_cmd: '["/usr/sbin/init"]'
+ # install various tools required to get the image up to usable levels
+ docker_image_commands:
+ - 'yum install -y crontabs tar wget openssl sysvinit-tools iproute which initscripts'
+CONFIG:
+ trace_limit: 200
diff --git a/spec/acceptance/nodesets/docker/debian-8.yml b/spec/acceptance/nodesets/docker/debian-8.yml
new file mode 100644
index 0000000..df5c319
--- /dev/null
+++ b/spec/acceptance/nodesets/docker/debian-8.yml
@@ -0,0 +1,11 @@
+HOSTS:
+ debian-8-x64:
+ platform: debian-8-amd64
+ hypervisor: docker
+ image: debian:8
+ docker_preserve_image: true
+ docker_cmd: '["/sbin/init"]'
+ docker_image_commands:
+ - 'apt-get update && apt-get install -y net-tools wget locales strace lsof && echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen'
+CONFIG:
+ trace_limit: 200
diff --git a/spec/acceptance/nodesets/docker/ubuntu-14.04.yml b/spec/acceptance/nodesets/docker/ubuntu-14.04.yml
new file mode 100644
index 0000000..b1efa58
--- /dev/null
+++ b/spec/acceptance/nodesets/docker/ubuntu-14.04.yml
@@ -0,0 +1,12 @@
+HOSTS:
+ ubuntu-1404-x64:
+ platform: ubuntu-14.04-amd64
+ hypervisor: docker
+ image: ubuntu:14.04
+ docker_preserve_image: true
+ docker_cmd: '["/sbin/init"]'
+ docker_image_commands:
+ # ensure that upstart is booting correctly in the container
+ - 'rm /usr/sbin/policy-rc.d && rm /sbin/initctl && dpkg-divert --rename --remove /sbin/initctl && apt-get update && apt-get install -y net-tools wget && locale-gen en_US.UTF-8'
+CONFIG:
+ trace_limit: 200
diff --git a/spec/acceptance/nodesets/fedora-18-x64.yml b/spec/acceptance/nodesets/fedora-18-x64.yml
deleted file mode 100644
index 1361649..0000000
--- a/spec/acceptance/nodesets/fedora-18-x64.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-HOSTS:
- fedora-18-x64:
- roles:
- - master
- platform: fedora-18-x86_64
- box : fedora-18-x64-vbox4210-nocm
- box_url : http://puppet-vagrant-boxes.puppetlabs.com/fedora-18-x64-vbox4210-nocm.box
- hypervisor : vagrant
-CONFIG:
- type: foss
diff --git a/spec/acceptance/nodesets/sles-11-x64.yml b/spec/acceptance/nodesets/sles-11-x64.yml
deleted file mode 100644
index 41abe21..0000000
--- a/spec/acceptance/nodesets/sles-11-x64.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-HOSTS:
- sles-11-x64.local:
- roles:
- - master
- platform: sles-11-x64
- box : sles-11sp1-x64-vbox4210-nocm
- box_url : http://puppet-vagrant-boxes.puppetlabs.com/sles-11sp1-x64-vbox4210-nocm.box
- hypervisor : vagrant
-CONFIG:
- type: foss
diff --git a/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml b/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml
deleted file mode 100644
index 5ca1514..0000000
--- a/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-HOSTS:
- ubuntu-server-10044-x64:
- roles:
- - master
- platform: ubuntu-10.04-amd64
- box : ubuntu-server-10044-x64-vbox4210-nocm
- box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-10044-x64-vbox4210-nocm.box
- hypervisor : vagrant
-CONFIG:
- type: foss
diff --git a/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml b/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml
deleted file mode 100644
index d065b30..0000000
--- a/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-HOSTS:
- ubuntu-server-12042-x64:
- roles:
- - master
- platform: ubuntu-12.04-amd64
- box : ubuntu-server-12042-x64-vbox4210-nocm
- box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box
- hypervisor : vagrant
-CONFIG:
- type: foss
diff --git a/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml b/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml
deleted file mode 100644
index cba1cd0..0000000
--- a/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-HOSTS:
- ubuntu-server-1404-x64:
- roles:
- - master
- platform: ubuntu-14.04-amd64
- box : puppetlabs/ubuntu-14.04-64-nocm
- box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm
- hypervisor : vagrant
-CONFIG:
- log_level : debug
- type: git
diff --git a/spec/acceptance/nodesets/windows-2003-i386.yml b/spec/acceptance/nodesets/windows-2003-i386.yml
deleted file mode 100644
index 47dadbd..0000000
--- a/spec/acceptance/nodesets/windows-2003-i386.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-HOSTS:
- ubuntu1204:
- roles:
- - master
- - database
- - dashboard
- platform: ubuntu-12.04-amd64
- template: ubuntu-1204-x86_64
- hypervisor: vcloud
- win2003_i386:
- roles:
- - agent
- - default
- platform: windows-2003-i386
- template: win-2003-i386
- hypervisor: vcloud
-CONFIG:
- nfs_server: none
- ssh:
- keys: "~/.ssh/id_rsa-acceptance"
- consoleport: 443
- datastore: instance0
- folder: Delivery/Quality Assurance/Enterprise/Dynamic
- resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
- pooling_api: http://vcloud.delivery.puppetlabs.net/
- pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/
diff --git a/spec/acceptance/nodesets/windows-2003-x86_64.yml b/spec/acceptance/nodesets/windows-2003-x86_64.yml
deleted file mode 100644
index 6a884bc..0000000
--- a/spec/acceptance/nodesets/windows-2003-x86_64.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-HOSTS:
- ubuntu1204:
- roles:
- - master
- - database
- - dashboard
- platform: ubuntu-12.04-amd64
- template: ubuntu-1204-x86_64
- hypervisor: vcloud
- win2003_x86_64:
- roles:
- - agent
- - default
- platform: windows-2003-x86_64
- template: win-2003-x86_64
- hypervisor: vcloud
-CONFIG:
- nfs_server: none
- ssh:
- keys: "~/.ssh/id_rsa-acceptance"
- consoleport: 443
- datastore: instance0
- folder: Delivery/Quality Assurance/Enterprise/Dynamic
- resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
- pooling_api: http://vcloud.delivery.puppetlabs.net/
- pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/
diff --git a/spec/acceptance/nodesets/windows-2008-x86_64.yml b/spec/acceptance/nodesets/windows-2008-x86_64.yml
deleted file mode 100644
index ae3c11d..0000000
--- a/spec/acceptance/nodesets/windows-2008-x86_64.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-HOSTS:
- ubuntu1204:
- roles:
- - master
- - database
- - dashboard
- platform: ubuntu-12.04-amd64
- template: ubuntu-1204-x86_64
- hypervisor: vcloud
- win2008_x86_64:
- roles:
- - agent
- - default
- platform: windows-2008-x86_64
- template: win-2008-x86_64
- hypervisor: vcloud
-CONFIG:
- nfs_server: none
- ssh:
- keys: "~/.ssh/id_rsa-acceptance"
- consoleport: 443
- datastore: instance0
- folder: Delivery/Quality Assurance/Enterprise/Dynamic
- resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
- pooling_api: http://vcloud.delivery.puppetlabs.net/
- pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/
diff --git a/spec/acceptance/nodesets/windows-2008r2-x86_64.yml b/spec/acceptance/nodesets/windows-2008r2-x86_64.yml
deleted file mode 100644
index 63923ac..0000000
--- a/spec/acceptance/nodesets/windows-2008r2-x86_64.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-HOSTS:
- ubuntu1204:
- roles:
- - master
- - database
- - dashboard
- platform: ubuntu-12.04-amd64
- template: ubuntu-1204-x86_64
- hypervisor: vcloud
- win2008r2:
- roles:
- - agent
- - default
- platform: windows-2008r2-x86_64
- template: win-2008r2-x86_64
- hypervisor: vcloud
-CONFIG:
- nfs_server: none
- ssh:
- keys: "~/.ssh/id_rsa-acceptance"
- consoleport: 443
- datastore: instance0
- folder: Delivery/Quality Assurance/Enterprise/Dynamic
- resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
- pooling_api: http://vcloud.delivery.puppetlabs.net/
- pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/
diff --git a/spec/acceptance/nodesets/windows-2012-x86_64.yml b/spec/acceptance/nodesets/windows-2012-x86_64.yml
deleted file mode 100644
index eaa4eca..0000000
--- a/spec/acceptance/nodesets/windows-2012-x86_64.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-HOSTS:
- ubuntu1204:
- roles:
- - master
- - database
- - dashboard
- platform: ubuntu-12.04-amd64
- template: ubuntu-1204-x86_64
- hypervisor: vcloud
- win2012:
- roles:
- - agent
- - default
- platform: windows-2012-x86_64
- template: win-2012-x86_64
- hypervisor: vcloud
-CONFIG:
- nfs_server: none
- ssh:
- keys: "~/.ssh/id_rsa-acceptance"
- consoleport: 443
- datastore: instance0
- folder: Delivery/Quality Assurance/Enterprise/Dynamic
- resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
- pooling_api: http://vcloud.delivery.puppetlabs.net/
- pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/
diff --git a/spec/acceptance/nodesets/windows-2012r2-x86_64.yml b/spec/acceptance/nodesets/windows-2012r2-x86_64.yml
deleted file mode 100644
index 1f0ea97..0000000
--- a/spec/acceptance/nodesets/windows-2012r2-x86_64.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-HOSTS:
- ubuntu1204:
- roles:
- - master
- - database
- - dashboard
- platform: ubuntu-12.04-amd64
- template: ubuntu-1204-x86_64
- hypervisor: vcloud
- win2012r2:
- roles:
- - agent
- - default
- platform: windows-2012r2-x86_64
- template: win-2012r2-x86_64
- hypervisor: vcloud
-CONFIG:
- nfs_server: none
- ssh:
- keys: "~/.ssh/id_rsa-acceptance"
- consoleport: 443
- datastore: instance0
- folder: Delivery/Quality Assurance/Enterprise/Dynamic
- resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
- pooling_api: http://vcloud.delivery.puppetlabs.net/
- pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/
diff --git a/spec/acceptance/parsejson_spec.rb b/spec/acceptance/parsejson_spec.rb
index 5097810..d0e3de8 100755
--- a/spec/acceptance/parsejson_spec.rb
+++ b/spec/acceptance/parsejson_spec.rb
@@ -16,10 +16,23 @@ 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, 'tests are using the default value')
+ notice(inline_template('a is <%= @ao.inspect %>'))
+ EOS
+
+ 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 json' do
+ pp = <<-EOS
+ $a = '{"hunter": "washere", "tests": "passing",}'
$ao = parsejson($a)
notice(inline_template('a is <%= @ao.inspect %>'))
EOS
@@ -29,6 +42,14 @@ describe 'parsejson function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('o
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
diff --git a/spec/acceptance/parseyaml_spec.rb b/spec/acceptance/parseyaml_spec.rb
index 5819837..64511f1 100755
--- a/spec/acceptance/parseyaml_spec.rb
+++ b/spec/acceptance/parseyaml_spec.rb
@@ -16,7 +16,21 @@ describe 'parseyaml function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('o
end
end
end
+
describe 'failure' do
+ it 'returns the default value on incorrect yaml' do
+ pp = <<-EOS
+ $a = "---\nhunter: washere\ntests: passing\n:"
+ $o = parseyaml($a, {'tests' => 'using the default value'})
+ $tests = $o['tests']
+ notice(inline_template('tests are <%= @tests.inspect %>'))
+ EOS
+
+ 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 yaml' do
pp = <<-EOS
$a = "---\nhunter: washere\ntests: passing\n:"
@@ -30,6 +44,15 @@ describe 'parseyaml function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('o
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
diff --git a/spec/acceptance/pw_hash_spec.rb b/spec/acceptance/pw_hash_spec.rb
new file mode 100644
index 0000000..cd4cb87
--- /dev/null
+++ b/spec/acceptance/pw_hash_spec.rb
@@ -0,0 +1,34 @@
+#! /usr/bin/env ruby -S rspec
+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', 'SLES']).include?(fact('operatingsystem')) do
+ describe 'success' do
+ it 'hashes passwords' do
+ pp = <<-EOS
+ $o = pw_hash('password', 'sha-512', 'salt')
+ notice(inline_template('pw_hash is <%= @o.inspect %>'))
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/pw_hash is "\$6\$salt\$IxDD3jeSOb5eB1CX5LBsqZFVkJdido3OUILO5Ifz5iwMuTS4XMS130MTSuDDl3aCI6WouIL9AjRbLCelDCy\.g\."/)
+ end
+ end
+
+ it 'returns nil if no password is provided' do
+ pp = <<-EOS
+ $o = pw_hash('', 'sha-512', 'salt')
+ notice(inline_template('pw_hash is <%= @o.inspect %>'))
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/pw_hash is nil/)
+ end
+ end
+ end
+ describe 'failure' do
+ it 'handles less than three arguments'
+ it 'handles more than three arguments'
+ it 'handles non strings'
+ end
+end
diff --git a/spec/acceptance/try_get_value_spec.rb b/spec/acceptance/try_get_value_spec.rb
new file mode 100755
index 0000000..c0bf38a
--- /dev/null
+++ b/spec/acceptance/try_get_value_spec.rb
@@ -0,0 +1,47 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'try_get_value function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+ describe 'success' do
+ it 'gets a value' do
+ pp = <<-EOS
+ $data = {
+ 'a' => { 'b' => 'passing'}
+ }
+
+ $tests = try_get_value($data, 'a/b')
+ notice(inline_template('tests are <%= @tests.inspect %>'))
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/tests are "passing"/)
+ end
+ end
+ end
+ describe 'failure' do
+ it 'uses a default value' do
+ pp = <<-EOS
+ $data = {
+ 'a' => { 'b' => 'passing'}
+ }
+
+ $tests = try_get_value($data, 'c/d', 'using the default value')
+ notice(inline_template('tests are <%= @tests.inspect %>'))
+ EOS
+
+ apply_manifest(pp, :catch_failures => true) do |r|
+ expect(r.stdout).to match(/using the default value/)
+ end
+ end
+
+ it 'raises error on incorrect number of arguments' do
+ pp = <<-EOS
+ $o = try_get_value()
+ EOS
+
+ apply_manifest(pp, :expect_failures => true) do |r|
+ expect(r.stderr).to match(/wrong number of arguments/i)
+ end
+ end
+ end
+end
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/acceptance/validate_array_spec.rb b/spec/acceptance/validate_array_spec.rb
index b53e98c..2f549d5 100755
--- a/spec/acceptance/validate_array_spec.rb
+++ b/spec/acceptance/validate_array_spec.rb
@@ -20,14 +20,14 @@ describe 'validate_array function', :unless => UNSUPPORTED_PLATFORMS.include?(fa
apply_manifest(pp, :catch_failures => true)
end
- it 'validates a non-array' do
- {
- %{validate_array({'a' => 'hash' })} => "Hash",
- %{validate_array('string')} => "String",
- %{validate_array(false)} => "FalseClass",
- %{validate_array(undef)} => "String"
- }.each do |pp,type|
- expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/a #{type}/)
+ [
+ %{validate_array({'a' => 'hash' })},
+ %{validate_array('string')},
+ %{validate_array(false)},
+ %{validate_array(undef)}
+ ].each do |pp|
+ it "rejects #{pp.inspect}" do
+ expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/is not an Array\. It looks to be a/)
end
end
end
diff --git a/spec/acceptance/validate_bool_spec.rb b/spec/acceptance/validate_bool_spec.rb
index c837f08..5c52d0f 100755
--- a/spec/acceptance/validate_bool_spec.rb
+++ b/spec/acceptance/validate_bool_spec.rb
@@ -20,14 +20,14 @@ describe 'validate_bool function', :unless => UNSUPPORTED_PLATFORMS.include?(fac
apply_manifest(pp, :catch_failures => true)
end
- it 'validates a non-bool' do
- {
- %{validate_bool('true')} => "String",
- %{validate_bool('false')} => "String",
- %{validate_bool([true])} => "Array",
- %{validate_bool(undef)} => "String",
- }.each do |pp,type|
- expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/a #{type}/)
+ [
+ %{validate_bool('true')},
+ %{validate_bool('false')},
+ %{validate_bool([true])},
+ %{validate_bool(undef)}
+ ].each do |pp|
+ it "rejects #{pp.inspect}" do
+ expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/is not a boolean\. It looks to be a/)
end
end
end
diff --git a/spec/acceptance/validate_hash_spec.rb b/spec/acceptance/validate_hash_spec.rb
index 52fb615..637df0a 100755
--- a/spec/acceptance/validate_hash_spec.rb
+++ b/spec/acceptance/validate_hash_spec.rb
@@ -20,14 +20,14 @@ describe 'validate_hash function', :unless => UNSUPPORTED_PLATFORMS.include?(fac
apply_manifest(pp, :catch_failures => true)
end
- it 'validates a non-hash' do
- {
- %{validate_hash('{ "not" => "hash" }')} => "String",
- %{validate_hash('string')} => "String",
- %{validate_hash(["array"])} => "Array",
- %{validate_hash(undef)} => "String",
- }.each do |pp,type|
- expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/a #{type}/)
+ [
+ %{validate_hash('{ "not" => "hash" }')},
+ %{validate_hash('string')},
+ %{validate_hash(["array"])},
+ %{validate_hash(undef)}
+ ].each do |pp|
+ it "rejects #{pp.inspect}" do
+ expect(apply_manifest(pp, :expect_failures => true).stderr).to match(//)
end
end
end
diff --git a/spec/acceptance/validate_string_spec.rb b/spec/acceptance/validate_string_spec.rb
index 8956f48..ae3468f 100755
--- a/spec/acceptance/validate_string_spec.rb
+++ b/spec/acceptance/validate_string_spec.rb
@@ -20,6 +20,13 @@ describe 'validate_string function', :unless => UNSUPPORTED_PLATFORMS.include?(f
apply_manifest(pp, :catch_failures => true)
end
+ it 'validates undef' do
+ pp = <<-EOS
+ validate_string(undef)
+ EOS
+
+ apply_manifest(pp, :catch_failures => true)
+ end
it 'validates a non-string' do
{
%{validate_string({ 'a' => 'hash' })} => "Hash",
diff --git a/spec/aliases/absolute_path_spec.rb b/spec/aliases/absolute_path_spec.rb
new file mode 100644
index 0000000..3fb9d12
--- /dev/null
+++ b/spec/aliases/absolute_path_spec.rb
@@ -0,0 +1,62 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::absolute_path', type: :class do
+ describe 'valid paths handling' do
+ %w{
+ C:/
+ C:\\
+ C:\\WINDOWS\\System32
+ C:/windows/system32
+ X:/foo/bar
+ X:\\foo\\bar
+ \\\\host\\windows
+ //host/windows
+ /
+ /var/tmp
+ /var/opt/../lib/puppet
+ }.each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+
+ describe 'invalid path handling' do
+ context 'garbage inputs' do
+ [
+ nil,
+ [ nil ],
+ [ nil, nil ],
+ { 'foo' => 'bar' },
+ { },
+ '',
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a match for Stdlib::Compat::Absolute_path/) }
+ end
+ end
+ end
+
+ context 'relative paths' do
+ %w{
+ relative1
+ .
+ ..
+ ./foo
+ ../foo
+ etc/puppetlabs/puppet
+ opt/puppet/bin
+ relative\\windows
+ }.each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a match for Stdlib::Compat::Absolute_path/) }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/aliases/absolutepath_spec.rb b/spec/aliases/absolutepath_spec.rb
new file mode 100644
index 0000000..aa435d7
--- /dev/null
+++ b/spec/aliases/absolutepath_spec.rb
@@ -0,0 +1,49 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::absolutepath', type: :class do
+ describe 'valid handling' do
+ %w{
+ /usr2/username/bin:/usr/local/bin:/usr/bin:.
+ C:/
+ C:\\
+ C:\\WINDOWS\\System32
+ C:/windows/system32
+ X:/foo/bar
+ X:\\foo\\bar
+ \\\\host\\windows
+ //host/windows
+ /var/tmp
+ /var/opt/../lib/puppet
+ }.each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+
+ describe 'invalid path handling' do
+ context 'garbage inputs' do
+ [
+ nil,
+ [ nil ],
+ [ nil, nil ],
+ { 'foo' => 'bar' },
+ { },
+ '',
+ "*/Users//nope",
+ "\\Users/hc/wksp/stdlib",
+ "C:noslashes",
+ "\\var\\tmp"
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a match for Variant/) }
+ end
+ end
+ end
+
+ end
+ end
+end
diff --git a/spec/aliases/array_spec.rb b/spec/aliases/array_spec.rb
new file mode 100644
index 0000000..d0f9877
--- /dev/null
+++ b/spec/aliases/array_spec.rb
@@ -0,0 +1,34 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::array', type: :class do
+ describe 'accepts arrays' do
+ [
+ [],
+ ['one'],
+ [1],
+ [{}],
+ [[]],
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+
+ describe 'rejects other values' do
+ [
+ '',
+ 'one',
+ '1',
+ {},
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a Stdlib::Compat::Array/) }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/aliases/bool_spec.rb b/spec/aliases/bool_spec.rb
new file mode 100644
index 0000000..78c57fc
--- /dev/null
+++ b/spec/aliases/bool_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::bool', type: :class do
+ describe 'accepts booleans' do
+ [
+ true,
+ false,
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+
+ describe 'rejects other values' do
+ [
+ [1],
+ [{}],
+ [true],
+ 'true',
+ 'false',
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a Stdlib::Compat::Bool/) }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/aliases/float_spec.rb b/spec/aliases/float_spec.rb
new file mode 100644
index 0000000..cc20758
--- /dev/null
+++ b/spec/aliases/float_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::float', type: :class do
+ describe 'accepts floats' do
+ [
+ 3.7,
+ '3.7',
+ -3.7,
+ '-342.2315e-12',
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+
+ describe 'rejects other values' do
+ [ true, 'true', false, 'false', 'iAmAString', '1test', '1 test', 'test 1', 'test 1 test', {}, { 'key' => 'value' }, { 1=> 2 }, '', :undef , 'x', 3, '3', -3, '-3'].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a value of type Float or Pattern(\[.*\]+)?/) }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/aliases/httpsurl_spec.rb b/spec/aliases/httpsurl_spec.rb
new file mode 100644
index 0000000..97ae006
--- /dev/null
+++ b/spec/aliases/httpsurl_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::httpsurl', type: :class do
+ describe 'valid handling' do
+ %w{
+ https://hello.com
+ https://notcreative.org
+ https://notexciting.co.uk
+ }.each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+
+ describe 'invalid path handling' do
+ context 'garbage inputs' do
+ [
+ nil,
+ [ nil ],
+ [ nil, nil ],
+ { 'foo' => 'bar' },
+ { },
+ '',
+ "httds://notquiteright.org",
+ "hptts:/nah",
+ "https;//notrightbutclose.org"
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a match for Stdlib::HTTPSUrl/) }
+ end
+ end
+ end
+
+ end
+ end
+end
diff --git a/spec/aliases/httpurl_spec.rb b/spec/aliases/httpurl_spec.rb
new file mode 100644
index 0000000..8bd57ca
--- /dev/null
+++ b/spec/aliases/httpurl_spec.rb
@@ -0,0 +1,43 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::httpurl', type: :class do
+ describe 'valid handling' do
+ %w{
+ https://hello.com
+ https://notcreative.org
+ https://canstillaccepthttps.co.uk
+ http://anhttp.com
+ http://runningoutofideas.gov
+ http://
+ }.each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+
+ describe 'invalid path handling' do
+ context 'garbage inputs' do
+ [
+ nil,
+ [ nil ],
+ [ nil, nil ],
+ { 'foo' => 'bar' },
+ { },
+ '',
+ "httds://notquiteright.org",
+ "hptts:/nah",
+ "https;//notrightbutclose.org"
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a match for Stdlib::HTTPUrl/) }
+ end
+ end
+ end
+
+ end
+ end
+end
diff --git a/spec/aliases/integer_spec.rb b/spec/aliases/integer_spec.rb
new file mode 100644
index 0000000..260090a
--- /dev/null
+++ b/spec/aliases/integer_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::integer', type: :class do
+ describe 'accepts integers' do
+ [
+ 3,
+ '3',
+ -3,
+ '-3',
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+
+ describe 'rejects other values' do
+ [ true, 'true', false, 'false', 'iAmAString', '1test', '1 test', 'test 1', 'test 1 test', {}, { 'key' => 'value' }, { 1=> 2 }, '', :undef , 'x', 3.7, '3.7',-3.7, '-342.2315e-12' ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a value of type Integer, Pattern(\[.*\]+)?, or Array/) }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/aliases/ip_address.rb b/spec/aliases/ip_address.rb
new file mode 100644
index 0000000..664bf24
--- /dev/null
+++ b/spec/aliases/ip_address.rb
@@ -0,0 +1,34 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::ip_address', type: :class do
+ describe 'accepts ipv4 and ipv6 addresses' do
+ [
+ '224.0.0.0',
+ '255.255.255.255',
+ '0.0.0.0',
+ '192.88.99.0',
+ '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
+ 'fa76:8765:34ac:0823:ab76:eee9:0987:1111'
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+ describe 'rejects other values' do
+ [
+ 'nope',
+ '77',
+ '4.4.4',
+ '2001:0db8:85a3:000000:0000:8a2e:0370:7334'
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a match for/) }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/aliases/ipv4_spec.rb b/spec/aliases/ipv4_spec.rb
new file mode 100644
index 0000000..210b4b1
--- /dev/null
+++ b/spec/aliases/ipv4_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::ipv4', type: :class do
+ describe 'accepts ipv4 addresses' do
+ SharedData::IPV4_PATTERNS.each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+ describe 'rejects other values' do
+ SharedData::IPV4_NEGATIVE_PATTERNS.each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a match for Stdlib::Compat::Ipv4/) }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/aliases/ipv6_spec.rb b/spec/aliases/ipv6_spec.rb
new file mode 100644
index 0000000..13d7c3e
--- /dev/null
+++ b/spec/aliases/ipv6_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::ipv6', type: :class do
+ describe 'accepts ipv6 addresses' do
+ [
+ '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
+ 'fa76:8765:34ac:0823:ab76:eee9:0987:1111'
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+ describe 'rejects other values' do
+ [
+ 'nope',
+ '77',
+ '4.4.4',
+ '2000:7334'
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a match for Stdlib::Compat::Ipv6/) }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/aliases/numeric_spec.rb b/spec/aliases/numeric_spec.rb
new file mode 100644
index 0000000..0e98bee
--- /dev/null
+++ b/spec/aliases/numeric_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::numeric', type: :class do
+ describe 'accepts numerics' do
+ [
+ 3,
+ '3',
+ -3,
+ '-3',
+ 3.7,
+ '3.7',
+ -3.7,
+ '-342.2315e-12',
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+
+ describe 'rejects other values' do
+ [ true, 'true', false, 'false', 'iAmAString', '1test', '1 test', 'test 1', 'test 1 test', {}, { 'key' => 'value' }, { 1=> 2 }, '', :undef , 'x' ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a value of type Numeric, Pattern(\[.*\]+)?, or Array/) }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/aliases/string_spec.rb b/spec/aliases/string_spec.rb
new file mode 100644
index 0000000..8a93585
--- /dev/null
+++ b/spec/aliases/string_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::string', type: :class do
+ describe 'accepts strings' do
+ [
+ '',
+ 'one',
+ nil,
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+
+ describe 'rejects other values' do
+ [
+ [],
+ {},
+ 1,
+ true,
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a String/) }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/aliases/unixpath_spec.rb b/spec/aliases/unixpath_spec.rb
new file mode 100644
index 0000000..aee161d
--- /dev/null
+++ b/spec/aliases/unixpath_spec.rb
@@ -0,0 +1,41 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::unixpath', type: :class do
+ describe 'valid handling' do
+ %w{
+ /usr2/username/bin:/usr/local/bin:/usr/bin:.
+ /var/tmp
+ /Users/helencampbell/workspace/puppetlabs-stdlib
+ }.each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+
+ describe 'invalid path handling' do
+ context 'garbage inputs' do
+ [
+ nil,
+ [ nil ],
+ [ nil, nil ],
+ { 'foo' => 'bar' },
+ { },
+ '',
+ "C:/whatever",
+ "\\var\\tmp",
+ "\\Users/hc/wksp/stdlib",
+ "*/Users//nope"
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a match for Stdlib::Unixpath/) }
+ end
+ end
+ end
+
+ end
+ end
+end
diff --git a/spec/aliases/windowspath_spec.rb b/spec/aliases/windowspath_spec.rb
new file mode 100644
index 0000000..c13794e
--- /dev/null
+++ b/spec/aliases/windowspath_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.5
+ describe 'test::windowspath', type: :class do
+ describe 'valid handling' do
+ %w{
+ C:\\
+ C:\\WINDOWS\\System32
+ C:/windows/system32
+ X:/foo/bar
+ X:\\foo\\bar
+ \\\\host\\windows
+ }.each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile }
+ end
+ end
+ end
+
+ describe 'invalid path handling' do
+ context 'garbage inputs' do
+ [
+ nil,
+ [ nil ],
+ [ nil, nil ],
+ { 'foo' => 'bar' },
+ { },
+ '',
+ "httds://notquiteright.org",
+ "/usr2/username/bin:/usr/local/bin:/usr/bin:.",
+ "C;//notright/here",
+ "C:noslashes"
+ ].each do |value|
+ describe value.inspect do
+ let(:params) {{ value: value }}
+ it { is_expected.to compile.and_raise_error(/parameter 'value' expects a match for Stdlib::Windowspath/) }
+ end
+ end
+ end
+
+ end
+ end
+end
diff --git a/spec/classes/anchor_spec.rb b/spec/classes/anchor_spec.rb
deleted file mode 100755
index 2d4455e..0000000
--- a/spec/classes/anchor_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-require 'spec_helper'
-require 'puppet_spec/compiler'
-
-describe "anchorrefresh" do
- include PuppetSpec::Compiler
-
- let :transaction do
- apply_compiled_manifest(<<-ANCHORCLASS)
- class anchored {
- anchor { 'anchored::begin': }
- ~> anchor { 'anchored::end': }
- }
-
- class anchorrefresh {
- notify { 'first': }
- ~> class { 'anchored': }
- ~> anchor { 'final': }
- }
-
- include anchorrefresh
- ANCHORCLASS
- end
-
- it 'propagates events through the anchored class' do
- resource = transaction.resource_status('Anchor[final]')
-
- expect(resource.restarted).to eq(true)
- end
-end
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/fixtures/test/manifests/absolute_path.pp b/spec/fixtures/test/manifests/absolute_path.pp
new file mode 100644
index 0000000..d77f6bd
--- /dev/null
+++ b/spec/fixtures/test/manifests/absolute_path.pp
@@ -0,0 +1,6 @@
+# Class to test the Stdlib::Compat::Absolute_path type alias
+class test::absolute_path(
+ Stdlib::Compat::Absolute_path $value,
+ ) {
+ notice("Success")
+}
diff --git a/spec/fixtures/test/manifests/absolutepath.pp b/spec/fixtures/test/manifests/absolutepath.pp
new file mode 100644
index 0000000..8321471
--- /dev/null
+++ b/spec/fixtures/test/manifests/absolutepath.pp
@@ -0,0 +1,6 @@
+# Class to test the Stdlib::Absolutepath type. Not to be confused with Stdlib::Compat::Absolute_path.
+class test::absolutepath(
+ Stdlib::Absolutepath $value,
+ ) {
+ notice("Success")
+}
diff --git a/spec/fixtures/test/manifests/array.pp b/spec/fixtures/test/manifests/array.pp
new file mode 100644
index 0000000..84b6a5b
--- /dev/null
+++ b/spec/fixtures/test/manifests/array.pp
@@ -0,0 +1,8 @@
+# Class to test the Stdlib::Compat::Array type alias
+class test::array(
+ Stdlib::Compat::Array $value,
+ ) {
+
+ notice("Success")
+
+}
diff --git a/spec/fixtures/test/manifests/bool.pp b/spec/fixtures/test/manifests/bool.pp
new file mode 100644
index 0000000..ab5b5ea
--- /dev/null
+++ b/spec/fixtures/test/manifests/bool.pp
@@ -0,0 +1,8 @@
+# Class to test the Stdlib::Compat::Bool type alias
+class test::bool(
+ Stdlib::Compat::Bool $value,
+ ) {
+
+ notice("Success")
+
+}
diff --git a/spec/fixtures/test/manifests/ensure_resources.pp b/spec/fixtures/test/manifests/ensure_resources.pp
new file mode 100644
index 0000000..bd26002
--- /dev/null
+++ b/spec/fixtures/test/manifests/ensure_resources.pp
@@ -0,0 +1,4 @@
+# A helper class to test the ensure_resources function
+class test::ensure_resources($resource_type, $title_hash, $attributes_hash) {
+ ensure_resources($resource_type, $title_hash, $attributes_hash)
+}
diff --git a/spec/fixtures/test/manifests/float.pp b/spec/fixtures/test/manifests/float.pp
new file mode 100644
index 0000000..03a603d
--- /dev/null
+++ b/spec/fixtures/test/manifests/float.pp
@@ -0,0 +1,8 @@
+# Class to test the Stdlib::Compat::Float type alias
+class test::float(
+ Stdlib::Compat::Float $value,
+ ) {
+
+ notice("Success")
+
+}
diff --git a/spec/fixtures/test/manifests/httpsurl.pp b/spec/fixtures/test/manifests/httpsurl.pp
new file mode 100644
index 0000000..9d6b92d
--- /dev/null
+++ b/spec/fixtures/test/manifests/httpsurl.pp
@@ -0,0 +1,6 @@
+# Class to test the Stdlib::HTTPSUrl type alias
+class test::httpsurl(
+ Stdlib::HTTPSUrl $value,
+ ) {
+ notice("Success")
+}
diff --git a/spec/fixtures/test/manifests/httpurl.pp b/spec/fixtures/test/manifests/httpurl.pp
new file mode 100644
index 0000000..abf869e
--- /dev/null
+++ b/spec/fixtures/test/manifests/httpurl.pp
@@ -0,0 +1,6 @@
+# Class to test the Stdlib::HTTPUrl type alias
+class test::httpurl(
+ Stdlib::HTTPUrl $value,
+ ) {
+ notice("Success")
+}
diff --git a/spec/fixtures/test/manifests/integer.pp b/spec/fixtures/test/manifests/integer.pp
new file mode 100644
index 0000000..a4f26df
--- /dev/null
+++ b/spec/fixtures/test/manifests/integer.pp
@@ -0,0 +1,8 @@
+# Class to test the Stdlib::Compat::Integer type alias
+class test::integer(
+ Stdlib::Compat::Integer $value,
+ ) {
+
+ notice("Success")
+
+}
diff --git a/spec/fixtures/test/manifests/ip_address.pp b/spec/fixtures/test/manifests/ip_address.pp
new file mode 100644
index 0000000..bbbd804
--- /dev/null
+++ b/spec/fixtures/test/manifests/ip_address.pp
@@ -0,0 +1,6 @@
+# Class to test the Stdlib::Compat::Ip_address type alias
+class test::ip_address(
+ Stdlib::Compat::Ip_address $value,
+ ) {
+ notice("Success")
+ }
diff --git a/spec/fixtures/test/manifests/ipv4.pp b/spec/fixtures/test/manifests/ipv4.pp
new file mode 100644
index 0000000..2e8022d
--- /dev/null
+++ b/spec/fixtures/test/manifests/ipv4.pp
@@ -0,0 +1,6 @@
+# Class to test the Stdlib::Compat::Ipv4 type alias
+class test::ipv4(
+ Stdlib::Compat::Ipv4 $value,
+ ) {
+ notice("Success")
+ }
diff --git a/spec/fixtures/test/manifests/ipv6.pp b/spec/fixtures/test/manifests/ipv6.pp
new file mode 100644
index 0000000..7912fd6
--- /dev/null
+++ b/spec/fixtures/test/manifests/ipv6.pp
@@ -0,0 +1,6 @@
+# Class to test the Stdlib::Compat::Ipv6 type alias
+class test::ipv6(
+ Stdlib::Compat::Ipv6 $value,
+ ) {
+ notice("Success")
+}
diff --git a/spec/fixtures/test/manifests/numeric.pp b/spec/fixtures/test/manifests/numeric.pp
new file mode 100644
index 0000000..2657ebc
--- /dev/null
+++ b/spec/fixtures/test/manifests/numeric.pp
@@ -0,0 +1,8 @@
+# Class to test the Stdlib::Compat::Numeric type alias
+class test::numeric(
+ Stdlib::Compat::Numeric $value,
+ ) {
+
+ notice("Success")
+
+}
diff --git a/spec/fixtures/test/manifests/string.pp b/spec/fixtures/test/manifests/string.pp
new file mode 100644
index 0000000..6508c70
--- /dev/null
+++ b/spec/fixtures/test/manifests/string.pp
@@ -0,0 +1,8 @@
+# Class to test the Stdlib::Compat::String type alias
+class test::string(
+ Stdlib::Compat::String $value,
+ ) {
+
+ notice("Success")
+
+}
diff --git a/spec/fixtures/test/manifests/unixpath.pp b/spec/fixtures/test/manifests/unixpath.pp
new file mode 100644
index 0000000..9311109
--- /dev/null
+++ b/spec/fixtures/test/manifests/unixpath.pp
@@ -0,0 +1,6 @@
+# Class to test the Stdlib::Unixpath type alias
+class test::unixpath(
+ Stdlib::Unixpath $value,
+ ) {
+ notice("Success")
+}
diff --git a/spec/fixtures/test/manifests/windowspath.pp b/spec/fixtures/test/manifests/windowspath.pp
new file mode 100644
index 0000000..af93ed3
--- /dev/null
+++ b/spec/fixtures/test/manifests/windowspath.pp
@@ -0,0 +1,6 @@
+# Class to test the Stdlib::Windowspath type alias
+class test::windowspath(
+ Stdlib::Windowspath $value,
+ ) {
+ notice("Success")
+}
diff --git a/spec/functions/abs_spec.rb b/spec/functions/abs_spec.rb
index 3c25ce2..7d2257b 100755
--- a/spec/functions/abs_spec.rb
+++ b/spec/functions/abs_spec.rb
@@ -1,25 +1,30 @@
-#! /usr/bin/env ruby -S rspec
-
require 'spec_helper'
-describe "the abs function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("abs")).to eq("function_abs")
- end
+describe 'abs' do
+ it { is_expected.not_to eq(nil) }
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_abs([]) }.to( raise_error(Puppet::ParseError))
+ describe 'signature validation in puppet3', :unless => RSpec.configuration.puppet_future do
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ it {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params(1, 2).and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
end
- it "should convert a negative number into a positive" do
- result = scope.function_abs(["-34"])
- expect(result).to(eq(34))
+ describe 'signature validation in puppet4', :if => RSpec.configuration.puppet_future do
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params().and_raise_error(ArgumentError) }
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params(1, 2).and_raise_error(ArgumentError) }
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params([]).and_raise_error(ArgumentError) }
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params({}).and_raise_error(ArgumentError) }
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params(true).and_raise_error(ArgumentError) }
end
- it "should do nothing with a positive number" do
- result = scope.function_abs(["5678"])
- expect(result).to(eq(5678))
- end
+ it { is_expected.to run.with_params(-34).and_return(34) }
+ it { is_expected.to run.with_params("-34").and_return(34) }
+ it { is_expected.to run.with_params(34).and_return(34) }
+ it { is_expected.to run.with_params("34").and_return(34) }
+ it { is_expected.to run.with_params(-34.5).and_return(34.5) }
+ it { is_expected.to run.with_params("-34.5").and_return(34.5) }
+ it { is_expected.to run.with_params(34.5).and_return(34.5) }
+ it { is_expected.to run.with_params("34.5").and_return(34.5) }
end
diff --git a/spec/functions/any2array_spec.rb b/spec/functions/any2array_spec.rb
index 87cd04b..70121f1 100755
--- a/spec/functions/any2array_spec.rb
+++ b/spec/functions/any2array_spec.rb
@@ -1,55 +1,15 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the any2array function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("any2array")).to eq("function_any2array")
- end
-
- it "should return an empty array if there is less than 1 argument" do
- result = scope.function_any2array([])
- expect(result).to(eq([]))
- end
-
- it "should convert boolean true to [ true ] " do
- result = scope.function_any2array([true])
- expect(result).to(eq([true]))
- end
-
- it "should convert one object to [object]" do
- result = scope.function_any2array(['one'])
- expect(result).to(eq(['one']))
- end
-
- it "should convert multiple objects to [objects]" do
- result = scope.function_any2array(['one', 'two'])
- expect(result).to(eq(['one', 'two']))
- end
-
- it "should return empty array it was called with" do
- result = scope.function_any2array([[]])
- expect(result).to(eq([]))
- end
-
- it "should return one-member array it was called with" do
- result = scope.function_any2array([['string']])
- expect(result).to(eq(['string']))
- end
-
- it "should return multi-member array it was called with" do
- result = scope.function_any2array([['one', 'two']])
- expect(result).to(eq(['one', 'two']))
- end
-
- it "should return members of a hash it was called with" do
- result = scope.function_any2array([{ 'key' => 'value' }])
- expect(result).to(eq(['key', 'value']))
- end
-
- it "should return an empty array if it was called with an empty hash" do
- result = scope.function_any2array([{ }])
- expect(result).to(eq([]))
- end
+describe "any2array" do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_return([]) }
+ it { is_expected.to run.with_params(true).and_return([true]) }
+ it { is_expected.to run.with_params('one').and_return(['one']) }
+ it { is_expected.to run.with_params('one', 'two').and_return(['one', 'two']) }
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(['one']).and_return(['one']) }
+ it { is_expected.to run.with_params(['one', 'two']).and_return(['one', 'two']) }
+ it { is_expected.to run.with_params({}).and_return([]) }
+ it { is_expected.to run.with_params({ 'key' => 'value' }).and_return(['key', 'value']) }
+ it { is_expected.to run.with_params({ 'key' => 'value' }).and_return(['key', 'value']) }
end
diff --git a/spec/functions/any2bool_spec.rb b/spec/functions/any2bool_spec.rb
new file mode 100755
index 0000000..9d351ce
--- /dev/null
+++ b/spec/functions/any2bool_spec.rb
@@ -0,0 +1,42 @@
+require 'spec_helper'
+
+describe 'any2bool' 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(true).and_return(true) }
+ it { is_expected.to run.with_params(false).and_return(false) }
+
+ it { is_expected.to run.with_params('1.5').and_return(true) }
+
+ describe 'when testing stringy values that mean "true"' do
+ [ 'TRUE','1', 't', 'y', 'true', 'yes'].each do |value|
+ it { is_expected.to run.with_params(value).and_return(true) }
+ end
+ end
+
+ describe 'when testing stringy values that mean "false"' do
+ [ 'FALSE','', '0', 'f', 'n', 'false', 'no', 'undef', 'undefined', nil, :undef ].each do |value|
+ it { is_expected.to run.with_params(value).and_return(false) }
+ end
+ end
+
+ describe 'when testing numeric values that mean "true"' do
+ [ 1,'1',1.5, '1.5'].each do |value|
+ it { is_expected.to run.with_params(value).and_return(true) }
+ end
+ end
+
+ describe 'when testing numeric that mean "false"' do
+ [ -1, '-1', -1.5, '-1.5', '0', 0 ].each do |value|
+ it { is_expected.to run.with_params(value).and_return(false) }
+ end
+ end
+
+ describe 'everything else returns true' do
+ [ [], {}, ['1'], [1], {:one => 1} ].each do |value|
+ it { is_expected.to run.with_params(value).and_return(true) }
+ end
+ end
+
+end
diff --git a/spec/functions/assert_private_spec.rb b/spec/functions/assert_private_spec.rb
new file mode 100755
index 0000000..355e0dd
--- /dev/null
+++ b/spec/functions/assert_private_spec.rb
@@ -0,0 +1,41 @@
+require 'spec_helper'
+
+describe 'assert_private' do
+ context 'when called from inside module' do
+ it "should not fail" do
+ scope.expects(:lookupvar).with('module_name').returns('foo')
+ scope.expects(:lookupvar).with('caller_module_name').returns('foo')
+
+ is_expected.to run.with_params()
+ end
+ end
+
+ context "when called from private class" do
+ before :each do
+ scope.expects(:lookupvar).with('module_name').returns('foo')
+ scope.expects(:lookupvar).with('caller_module_name').returns('bar')
+ end
+
+ it "should fail with a class error message" do
+ scope.source.expects(:name).returns('foo::baz')
+ scope.source.expects(:type).returns('hostclass')
+
+ is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /Class foo::baz is private/)
+ end
+
+ context "with an explicit failure message" do
+ it { is_expected.to run.with_params('failure message!').and_raise_error(Puppet::ParseError, /failure message!/) }
+ end
+ end
+
+ context "when called from private definition" do
+ it "should fail with a class error message" do
+ scope.expects(:lookupvar).with('module_name').returns('foo')
+ scope.expects(:lookupvar).with('caller_module_name').returns('bar')
+ scope.source.expects(:name).returns('foo::baz')
+ scope.source.expects(:type).returns('definition')
+
+ is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /Definition foo::baz is private/)
+ end
+ end
+end
diff --git a/spec/functions/base64_spec.rb b/spec/functions/base64_spec.rb
index e93fafc..842a37a 100755
--- a/spec/functions/base64_spec.rb
+++ b/spec/functions/base64_spec.rb
@@ -1,34 +1,37 @@
-#! /usr/bin/env ruby -S rspec
-
require 'spec_helper'
-describe "the base64 function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("base64")).to eq("function_base64")
- end
-
- it "should raise a ParseError if there are other than 2 arguments" do
- expect { scope.function_base64([]) }.to(raise_error(Puppet::ParseError))
- expect { scope.function_base64(["asdf"]) }.to(raise_error(Puppet::ParseError))
- expect { scope.function_base64(["asdf","moo","cow"]) }.to(raise_error(Puppet::ParseError))
- end
-
- it "should raise a ParseError if argument 1 isn't 'encode' or 'decode'" do
- expect { scope.function_base64(["bees","astring"]) }.to(raise_error(Puppet::ParseError, /first argument must be one of/))
- end
-
- it "should raise a ParseError if argument 2 isn't a string" do
- expect { scope.function_base64(["encode",["2"]]) }.to(raise_error(Puppet::ParseError, /second argument must be a string/))
- end
-
- it "should encode a encoded string" do
- result = scope.function_base64(["encode",'thestring'])
- expect(result).to match(/\AdGhlc3RyaW5n\n\Z/)
- end
- it "should decode a base64 encoded string" do
- result = scope.function_base64(["decode",'dGhlc3RyaW5n'])
- expect(result).to eq('thestring')
- end
+describe 'base64' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params("one").and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params("one", "two").and_raise_error(Puppet::ParseError, /first argument must be one of/) }
+ it { is_expected.to run.with_params("encode", ["two"]).and_raise_error(Puppet::ParseError, /second argument must be a string/) }
+ 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", "three").and_raise_error(Puppet::ParseError, /third argument must be one of/) }
+ it { is_expected.to run.with_params("decode", "dGhlc3RyaW5n\n", "strict").and_raise_error(ArgumentError) }
+
+ it { is_expected.to run.with_params("encode", "thestring").and_return("dGhlc3RyaW5n\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") }
+
+ it { is_expected.to run.with_params("encode", "thestring", "default").and_return("dGhlc3RyaW5n\n") }
+ it { is_expected.to run.with_params("decode", "dGhlc3RyaW5n", "default").and_return("thestring") }
+ it { is_expected.to run.with_params("decode", "dGhlc3RyaW5n\n", "default").and_return("thestring") }
+
+ it { is_expected.to run.with_params("encode", "thestring", "strict").and_return("dGhlc3RyaW5n") }
+ it { is_expected.to run.with_params("decode", "dGhlc3RyaW5n", "strict").and_return("thestring") }
+
+ 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", "YSB2ZXJ5IGxvbmcgc3RyaW5nIHRoYXQgd2lsbCBjYXVzZSB0aGUgYmFzZTY0\nIGVuY29kZXIgdG8gcHJvZHVjZSBvdXRwdXQgd2l0aCBtdWx0aXBsZSBsaW5l\ncw==\n").and_return("a very long string that will cause the base64 encoder to produce output with multiple lines") }
+ it { is_expected.to run.with_params("decode", "YSB2ZXJ5IGxvbmcgc3RyaW5nIHRoYXQgd2lsbCBjYXVzZSB0aGUgYmFzZTY0IGVuY29kZXIgdG8gcHJvZHVjZSBvdXRwdXQgd2l0aCBtdWx0aXBsZSBsaW5lcw==").and_return("a very long string that will cause the base64 encoder to produce output with multiple lines") }
+
+ it { is_expected.to run.with_params("encode", "a very long string that will cause the base64 encoder to produce output with multiple lines", "strict").and_return("YSB2ZXJ5IGxvbmcgc3RyaW5nIHRoYXQgd2lsbCBjYXVzZSB0aGUgYmFzZTY0IGVuY29kZXIgdG8gcHJvZHVjZSBvdXRwdXQgd2l0aCBtdWx0aXBsZSBsaW5lcw==") }
+ it { is_expected.to run.with_params("decode", "YSB2ZXJ5IGxvbmcgc3RyaW5nIHRoYXQgd2lsbCBjYXVzZSB0aGUgYmFzZTY0IGVuY29kZXIgdG8gcHJvZHVjZSBvdXRwdXQgd2l0aCBtdWx0aXBsZSBsaW5lcw==").and_return("a very long string that will cause the base64 encoder to produce output with multiple lines") }
+ it { is_expected.to run.with_params("decode", "YSB2ZXJ5IGxvbmcgc3RyaW5nIHRoYXQgd2lsbCBjYXVzZSB0aGUgYmFzZTY0IGVuY29kZXIgdG8gcHJvZHVjZSBvdXRwdXQgd2l0aCBtdWx0aXBsZSBsaW5lcw==", "strict").and_return("a very long string that will cause the base64 encoder to produce output with multiple lines") }
+
+ it { is_expected.to run.with_params("encode", "https://www.google.com.tw/?gws_rd=ssl#q=hello+world", "urlsafe").and_return("aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS50dy8_Z3dzX3JkPXNzbCNxPWhlbGxvK3dvcmxk") }
+ it { is_expected.to run.with_params("decode", "aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS50dy8_Z3dzX3JkPXNzbCNxPWhlbGxvK3dvcmxk", "urlsafe").and_return("https://www.google.com.tw/?gws_rd=ssl#q=hello+world") }
+
+ it { is_expected.to run.with_params("encode", "https://github.com/puppetlabs/puppetlabs-stdlib/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+Add", "urlsafe").and_return("aHR0cHM6Ly9naXRodWIuY29tL3B1cHBldGxhYnMvcHVwcGV0bGFicy1zdGRsaWIvcHVsbHM_dXRmOD0lRTIlOUMlOTMmcT1pcyUzQXByK2lzJTNBb3BlbitBZGQ=") }
+ it { is_expected.to run.with_params("decode", "aHR0cHM6Ly9naXRodWIuY29tL3B1cHBldGxhYnMvcHVwcGV0bGFicy1zdGRsaWIvcHVsbHM_dXRmOD0lRTIlOUMlOTMmcT1pcyUzQXByK2lzJTNBb3BlbitBZGQ=", "urlsafe").and_return("https://github.com/puppetlabs/puppetlabs-stdlib/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+Add") }
end
diff --git a/spec/functions/basename_spec.rb b/spec/functions/basename_spec.rb
new file mode 100755
index 0000000..c84e192
--- /dev/null
+++ b/spec/functions/basename_spec.rb
@@ -0,0 +1,14 @@
+require 'spec_helper'
+
+describe 'basename' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one', 'two', 'three').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('/path/to/a/file.ext', []).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('/path/to/a/file.ext').and_return('file.ext') }
+ it { is_expected.to run.with_params('relative_path/to/a/file.ext').and_return('file.ext') }
+ it { is_expected.to run.with_params('/path/to/a/file.ext', '.ext').and_return('file') }
+ it { is_expected.to run.with_params('relative_path/to/a/file.ext', '.ext').and_return('file') }
+ it { is_expected.to run.with_params('scheme:///path/to/a/file.ext').and_return('file.ext') }
+end
diff --git a/spec/functions/bool2num_spec.rb b/spec/functions/bool2num_spec.rb
index 3904d7e..e506859 100755
--- a/spec/functions/bool2num_spec.rb
+++ b/spec/functions/bool2num_spec.rb
@@ -1,38 +1,14 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the bool2num function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'bool2num' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("bool2num")).to eq("function_bool2num")
+ [ true, 'true', AlsoString.new('true') ].each do |truthy|
+ it { is_expected.to run.with_params(truthy).and_return(1) }
end
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_bool2num([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should convert true to 1" do
- result = scope.function_bool2num([true])
- expect(result).to(eq(1))
- end
-
- it "should convert 'true' to 1" do
- result = scope.function_bool2num(['true'])
- result.should(eq(1))
- end
-
- it "should convert 'false' to 0" do
- result = scope.function_bool2num(['false'])
- expect(result).to(eq(0))
- end
-
- it "should accept objects which extend String" do
- class AlsoString < String
- end
-
- value = AlsoString.new('true')
- result = scope.function_bool2num([value])
- result.should(eq(1))
+ [ false, 'false', AlsoString.new('false') ].each do |falsey|
+ it { is_expected.to run.with_params(falsey).and_return(0) }
end
end
diff --git a/spec/functions/bool2str_spec.rb b/spec/functions/bool2str_spec.rb
new file mode 100755
index 0000000..23a754b
--- /dev/null
+++ b/spec/functions/bool2str_spec.rb
@@ -0,0 +1,17 @@
+require 'spec_helper'
+
+describe 'bool2str' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ [ 'true', 'false', nil, :undef, ''].each do |invalid|
+ it { is_expected.to run.with_params(invalid).and_raise_error(Puppet::ParseError) }
+ end
+ it { is_expected.to run.with_params(true, 'yes', 'no', 'maybe').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(true, 'maybe').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(true, 0, 1).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(true).and_return("true") }
+ it { is_expected.to run.with_params(false).and_return("false") }
+ it { is_expected.to run.with_params(true, 'yes', 'no').and_return("yes") }
+ it { is_expected.to run.with_params(false, 'yes', 'no').and_return("no") }
+
+end
diff --git a/spec/functions/camelcase_spec.rb b/spec/functions/camelcase_spec.rb
new file mode 100755
index 0000000..c78aa62
--- /dev/null
+++ b/spec/functions/camelcase_spec.rb
@@ -0,0 +1,17 @@
+require 'spec_helper'
+
+describe 'camelcase' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(100).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params("abc").and_return("Abc") }
+ it { is_expected.to run.with_params("aa_bb_cc").and_return("AaBbCc") }
+ it { is_expected.to run.with_params("_aa__bb__cc_").and_return("AaBbCc") }
+ it { is_expected.to run.with_params("100").and_return("100") }
+ it { is_expected.to run.with_params("1_00").and_return("100") }
+ it { is_expected.to run.with_params("_").and_return("") }
+ it { is_expected.to run.with_params("").and_return("") }
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(["abc", "aa_bb_cc"]).and_return(["Abc", "AaBbCc"]) }
+ it { is_expected.to run.with_params(["abc", 1, "aa_bb_cc"]).and_return(["Abc", 1, "AaBbCc"]) }
+end
diff --git a/spec/functions/capitalize_spec.rb b/spec/functions/capitalize_spec.rb
index fd0e92b..7ce2e16 100755
--- a/spec/functions/capitalize_spec.rb
+++ b/spec/functions/capitalize_spec.rb
@@ -1,28 +1,15 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the capitalize function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("capitalize")).to eq("function_capitalize")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_capitalize([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should capitalize the beginning of a string" do
- result = scope.function_capitalize(["abc"])
- expect(result).to(eq("Abc"))
- end
-
- it "should accept objects which extend String" do
- class AlsoString < String
- end
-
- value = AlsoString.new('abc')
- result = scope.function_capitalize([value])
- result.should(eq('Abc'))
- end
+describe 'capitalize' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(100).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params("one").and_return("One") }
+ it { is_expected.to run.with_params("one two").and_return("One two") }
+ it { is_expected.to run.with_params("ONE TWO").and_return("One two") }
+
+ it { is_expected.to run.with_params(AlsoString.new("one")).and_return("One") }
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(["one", "two"]).and_return(["One", "Two"]) }
+ it { is_expected.to run.with_params(["one", 1, "two"]).and_return(["One", 1, "Two"]) }
end
diff --git a/spec/functions/ceiling_spec.rb b/spec/functions/ceiling_spec.rb
new file mode 100755
index 0000000..567426f
--- /dev/null
+++ b/spec/functions/ceiling_spec.rb
@@ -0,0 +1,13 @@
+require 'spec_helper'
+
+describe 'ceiling' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params("foo").and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(34).and_return(34) }
+ it { is_expected.to run.with_params(-34).and_return(-34) }
+ it { is_expected.to run.with_params(33.1).and_return(34) }
+ it { is_expected.to run.with_params(-33.1).and_return(-33) }
+end
+
diff --git a/spec/functions/chomp_spec.rb b/spec/functions/chomp_spec.rb
index b1e1e60..6878742 100755
--- a/spec/functions/chomp_spec.rb
+++ b/spec/functions/chomp_spec.rb
@@ -1,28 +1,20 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the chomp function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'chomp' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) }
+ it {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params("a", "b").and_raise_error(Puppet::ParseError)
+ }
+ it { is_expected.to run.with_params("one").and_return("one") }
+ it { is_expected.to run.with_params("one\n").and_return("one") }
+ it { is_expected.to run.with_params("one\n\n").and_return("one\n") }
+ it { is_expected.to run.with_params(["one\n", "two", "three\n"]).and_return(["one", "two", "three"]) }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("chomp")).to eq("function_chomp")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_chomp([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should chomp the end of a string" do
- result = scope.function_chomp(["abc\n"])
- expect(result).to(eq("abc"))
- end
-
- it "should accept objects which extend String" do
- class AlsoString < String
- end
-
- value = AlsoString.new("abc\n")
- result = scope.function_chomp([value])
- result.should(eq("abc"))
- end
+ it { is_expected.to run.with_params(AlsoString.new("one")).and_return("one") }
+ it { is_expected.to run.with_params(AlsoString.new("one\n")).and_return("one") }
+ it { is_expected.to run.with_params(AlsoString.new("one\n\n")).and_return("one\n") }
+ it { is_expected.to run.with_params([AlsoString.new("one\n"), AlsoString.new("two"), "three\n"]).and_return(["one", "two", "three"]) }
end
diff --git a/spec/functions/chop_spec.rb b/spec/functions/chop_spec.rb
index c8a1951..db7d18b 100755
--- a/spec/functions/chop_spec.rb
+++ b/spec/functions/chop_spec.rb
@@ -1,28 +1,20 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the chop function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'chop' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) }
+ it {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params("a", "b").and_raise_error(Puppet::ParseError)
+ }
+ it { is_expected.to run.with_params("one").and_return("on") }
+ it { is_expected.to run.with_params("one\n").and_return("one") }
+ it { is_expected.to run.with_params("one\n\n").and_return("one\n") }
+ it { is_expected.to run.with_params(["one\n", "two", "three\n"]).and_return(["one", "tw", "three"]) }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("chop")).to eq("function_chop")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_chop([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should chop the end of a string" do
- result = scope.function_chop(["asdf\n"])
- expect(result).to(eq("asdf"))
- end
-
- it "should accept objects which extend String" do
- class AlsoString < String
- end
-
- value = AlsoString.new("abc\n")
- result = scope.function_chop([value])
- result.should(eq('abc'))
- end
+ it { is_expected.to run.with_params(AlsoString.new("one")).and_return("on") }
+ it { is_expected.to run.with_params(AlsoString.new("one\n")).and_return("one") }
+ it { is_expected.to run.with_params(AlsoString.new("one\n\n")).and_return("one\n") }
+ it { is_expected.to run.with_params([AlsoString.new("one\n"), AlsoString.new("two"), "three\n"]).and_return(["one", "tw", "three"]) }
end
diff --git a/spec/functions/clamp_spec.rb b/spec/functions/clamp_spec.rb
new file mode 100644
index 0000000..3e2fe7a
--- /dev/null
+++ b/spec/functions/clamp_spec.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+describe 'clamp' 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([]).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(12, 88, 71, 190).and_raise_error(Puppet::ParseError, /Wrong number of arguments, need three to clamp/) }
+ it { is_expected.to run.with_params('12string', 88, 15).and_raise_error(Puppet::ParseError, /Required explicit numeric/) }
+ it { is_expected.to run.with_params(1, 2, {'a' => 55}).and_raise_error(Puppet::ParseError, /The Hash type is not allowed/) }
+ it { is_expected.to run.with_params('24', [575, 187]).and_return(187) }
+ it { is_expected.to run.with_params([4, 3, '99']).and_return(4) }
+ it { is_expected.to run.with_params(16, 750, 88).and_return(88) }
+ it { is_expected.to run.with_params([3, 873], 73).and_return(73) }
+ it { is_expected.to run.with_params([4], 8, 75).and_return(8) }
+ it { is_expected.to run.with_params([6], [31], 9911).and_return(31) }
+end
diff --git a/spec/functions/concat_spec.rb b/spec/functions/concat_spec.rb
index 49fa6bb..eb76233 100755
--- a/spec/functions/concat_spec.rb
+++ b/spec/functions/concat_spec.rb
@@ -1,50 +1,25 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the concat function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should raise a ParseError if the client does not provide at least two arguments" do
- expect { scope.function_concat([]) }.to(raise_error(Puppet::ParseError))
- expect { scope.function_concat([[1]]) }.to(raise_error(Puppet::ParseError))
- end
-
- it "should raise a ParseError if the first parameter is not an array" do
- expect { scope.function_concat([1, []])}.to(raise_error(Puppet::ParseError))
- end
-
- it "should not raise a ParseError if the client provides more than two arguments" do
- expect { scope.function_concat([[1],[2],[3]]) }.not_to raise_error
- end
-
- it "should be able to concat an array" do
- result = scope.function_concat([['1','2','3'],['4','5','6']])
- expect(result).to(eq(['1','2','3','4','5','6']))
- end
-
- it "should be able to concat a primitive to an array" do
- result = scope.function_concat([['1','2','3'],'4'])
- expect(result).to(eq(['1','2','3','4']))
- end
-
- it "should not accidentally flatten nested arrays" do
- result = scope.function_concat([['1','2','3'],[['4','5'],'6']])
- expect(result).to(eq(['1','2','3',['4','5'],'6']))
- end
+describe 'concat' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([1]).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(1, [2]).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([1], [2], [3]).and_return([1, 2, 3]) }
+ it { is_expected.to run.with_params(['1','2','3'],['4','5','6']).and_return(['1','2','3','4','5','6']) }
+ it { is_expected.to run.with_params(['1','2','3'],'4').and_return(['1','2','3','4']) }
+ it { is_expected.to run.with_params(['1','2','3'],[['4','5'],'6']).and_return(['1','2','3',['4','5'],'6']) }
+ it { is_expected.to run.with_params(['1','2'],['3','4'],['5','6']).and_return(['1','2','3','4','5','6']) }
+ it { is_expected.to run.with_params(['1','2'],'3','4',['5','6']).and_return(['1','2','3','4','5','6']) }
+ it { is_expected.to run.with_params([{"a" => "b"}], {"c" => "d", "e" => "f"}).and_return([{"a" => "b"}, {"c" => "d", "e" => "f"}]) }
it "should leave the original array intact" do
- array_original = ['1','2','3']
- result = scope.function_concat([array_original,['4','5','6']])
- array_original.should(eq(['1','2','3']))
- end
-
- it "should be able to concat multiple arrays" do
- result = scope.function_concat([['1','2','3'],['4','5','6'],['7','8','9']])
- expect(result).to(eq(['1','2','3','4','5','6','7','8','9']))
- end
-
- it "should be able to concat mix of primitives and arrays to a final array" do
- result = scope.function_concat([['1','2','3'],'4',['5','6','7']])
- expect(result).to(eq(['1','2','3','4','5','6','7']))
+ argument1 = ['1','2','3']
+ original1 = argument1.dup
+ argument2 = ['4','5','6']
+ original2 = argument2.dup
+ result = subject.call([argument1,argument2])
+ expect(argument1).to eq(original1)
+ expect(argument2).to eq(original2)
end
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/count_spec.rb b/spec/functions/count_spec.rb
index f8f1d48..c8d1960 100755
--- a/spec/functions/count_spec.rb
+++ b/spec/functions/count_spec.rb
@@ -1,31 +1,18 @@
-#! /usr/bin/env ruby -S rspec
-
require 'spec_helper'
-describe "the count function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("count")).to eq("function_count")
- end
-
- it "should raise a ArgumentError if there is more than 2 arguments" do
- expect { scope.function_count(['foo', 'bar', 'baz']) }.to( raise_error(ArgumentError))
- end
-
- it "should be able to count arrays" do
- expect(scope.function_count([["1","2","3"]])).to(eq(3))
- end
-
- it "should be able to count matching elements in arrays" do
- expect(scope.function_count([["1", "2", "2"], "2"])).to(eq(2))
- end
-
- it "should not count nil or empty strings" do
- expect(scope.function_count([["foo","bar",nil,""]])).to(eq(2))
- end
-
- it 'does not count an undefined hash key or an out of bound array index (which are both :undef)' do
- expect(scope.function_count([["foo",:undef,:undef]])).to eq(1)
- end
+describe 'count' 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("one").and_raise_error(ArgumentError) }
+ it { is_expected.to run.with_params("one", "two").and_return(1) }
+ it {
+ pending("should actually be like this, and not like above")
+ is_expected.to run.with_params("one", "two").and_raise_error(ArgumentError)
+ }
+ it { is_expected.to run.with_params("one", "two", "three").and_raise_error(ArgumentError) }
+ it { is_expected.to run.with_params(["one", "two", "three"]).and_return(3) }
+ it { is_expected.to run.with_params(["one", "two", "two"], "two").and_return(2) }
+ it { is_expected.to run.with_params(["one", nil, "two"]).and_return(2) }
+ it { is_expected.to run.with_params(["one", "", "two"]).and_return(2) }
+ it { is_expected.to run.with_params(["one", :undef, "two"]).and_return(2) }
end
diff --git a/spec/functions/deep_merge_spec.rb b/spec/functions/deep_merge_spec.rb
index 7087904..397e048 100755
--- a/spec/functions/deep_merge_spec.rb
+++ b/spec/functions/deep_merge_spec.rb
@@ -1,105 +1,55 @@
-#! /usr/bin/env ruby -S rspec
-
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:deep_merge) do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- describe 'when calling deep_merge from puppet' do
- it "should not compile when no arguments are passed" do
- skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./
- Puppet[:code] = '$x = deep_merge()'
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /wrong number of arguments/)
- end
-
- it "should not compile when 1 argument is passed" do
- skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./
- Puppet[:code] = "$my_hash={'one' => 1}\n$x = deep_merge($my_hash)"
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /wrong number of arguments/)
- end
+describe 'deep_merge' 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({ 'key' => 'value' }).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ it { is_expected.to run.with_params({}, '2').and_raise_error(Puppet::ParseError, /unexpected argument type String/) }
+ it { is_expected.to run.with_params({}, 2).and_raise_error(Puppet::ParseError, /unexpected argument type Fixnum/) }
+ it { is_expected.to run.with_params({}, '').and_return({}) }
+ it { is_expected.to run.with_params({}, {}).and_return({}) }
+ it { is_expected.to run.with_params({}, {}, {}).and_return({}) }
+ it { is_expected.to run.with_params({}, {}, {}, {}).and_return({}) }
+ it { is_expected.to run.with_params({'key' => 'value'}, '').and_return({'key' => 'value'}) }
+ it { is_expected.to run.with_params({'key1' => 'value1'}, {'key2' => 'value2' }).and_return({'key1' => 'value1', 'key2' => 'value2'}) }
+
+ describe 'when arguments have key collisions' do
+ it 'should prefer values from the last hash' do
+ is_expected.to run \
+ .with_params(
+ {'key1' => 'value1', 'key2' => 'value2' },
+ {'key2' => 'replacement_value', 'key3' => 'value3'}) \
+ .and_return(
+ {'key1' => 'value1', 'key2' => 'replacement_value', 'key3' => 'value3'})
+ end
+ it { is_expected.to run \
+ .with_params({'key1' => 'value1'}, {'key1' => 'value2'}, {'key1' => 'value3'}) \
+ .and_return({'key1' => 'value3' })
+ }
end
- describe 'when calling deep_merge on the scope instance' do
- it 'should require all parameters are hashes' do
- expect { new_hash = scope.function_deep_merge([{}, '2'])}.to raise_error(Puppet::ParseError, /unexpected argument type String/)
- expect { new_hash = scope.function_deep_merge([{}, 2])}.to raise_error(Puppet::ParseError, /unexpected argument type Fixnum/)
- end
-
- it 'should accept empty strings as puppet undef' do
- expect { new_hash = scope.function_deep_merge([{}, ''])}.not_to raise_error
- end
-
- it 'should be able to deep_merge two hashes' do
- new_hash = scope.function_deep_merge([{'one' => '1', 'two' => '1'}, {'two' => '2', 'three' => '2'}])
- expect(new_hash['one']).to eq('1')
- expect(new_hash['two']).to eq('2')
- expect(new_hash['three']).to eq('2')
- end
-
- it 'should deep_merge multiple hashes' do
- hash = scope.function_deep_merge([{'one' => 1}, {'one' => '2'}, {'one' => '3'}])
- expect(hash['one']).to eq('3')
- end
-
- it 'should accept empty hashes' do
- expect(scope.function_deep_merge([{},{},{}])).to eq({})
- end
-
- it 'should deep_merge subhashes' do
- hash = scope.function_deep_merge([{'one' => 1}, {'two' => 2, 'three' => { 'four' => 4 } }])
- expect(hash['one']).to eq(1)
- expect(hash['two']).to eq(2)
- expect(hash['three']).to eq({ 'four' => 4 })
- end
-
- it 'should append to subhashes' do
- hash = scope.function_deep_merge([{'one' => { 'two' => 2 } }, { 'one' => { 'three' => 3 } }])
- expect(hash['one']).to eq({ 'two' => 2, 'three' => 3 })
- end
-
- it 'should append to subhashes 2' do
- hash = scope.function_deep_merge([{'one' => 1, 'two' => 2, 'three' => { 'four' => 4 } }, {'two' => 'dos', 'three' => { 'five' => 5 } }])
- expect(hash['one']).to eq(1)
- expect(hash['two']).to eq('dos')
- expect(hash['three']).to eq({ 'four' => 4, 'five' => 5 })
- end
-
- it 'should append to subhashes 3' do
- hash = scope.function_deep_merge([{ 'key1' => { 'a' => 1, 'b' => 2 }, 'key2' => { 'c' => 3 } }, { 'key1' => { 'b' => 99 } }])
- expect(hash['key1']).to eq({ 'a' => 1, 'b' => 99 })
- expect(hash['key2']).to eq({ 'c' => 3 })
- end
-
- it 'should not change the original hashes' do
- hash1 = {'one' => { 'two' => 2 } }
- hash2 = { 'one' => { 'three' => 3 } }
- hash = scope.function_deep_merge([hash1, hash2])
- expect(hash1).to eq({'one' => { 'two' => 2 } })
- expect(hash2).to eq({ 'one' => { 'three' => 3 } })
- expect(hash['one']).to eq({ 'two' => 2, 'three' => 3 })
- end
+ describe 'when arguments have subhashes' do
+ it { is_expected.to run \
+ .with_params({'key1' => 'value1'}, {'key2' => 'value2', 'key3' => {'subkey1' => 'value4'}}) \
+ .and_return( {'key1' => 'value1', 'key2' => 'value2', 'key3' => {'subkey1' => 'value4'}})
+ }
+ it { is_expected.to run \
+ .with_params({'key1' => {'subkey1' => 'value1'}}, {'key1' => {'subkey2' => 'value2'}}) \
+ .and_return( {'key1' => {'subkey1' => 'value1', 'subkey2' => 'value2'}})
+ }
+ it { is_expected.to run \
+ .with_params({'key1' => {'subkey1' => {'subsubkey1' => 'value1'}}}, {'key1' => {'subkey1' => {'subsubkey1' => 'value2'}}}) \
+ .and_return( {'key1' => {'subkey1' => {'subsubkey1' => 'value2'}}})
+ }
+ end
- it 'should not change the original hashes 2' do
- hash1 = {'one' => { 'two' => [1,2] } }
- hash2 = { 'one' => { 'three' => 3 } }
- hash = scope.function_deep_merge([hash1, hash2])
- expect(hash1).to eq({'one' => { 'two' => [1,2] } })
- expect(hash2).to eq({ 'one' => { 'three' => 3 } })
- expect(hash['one']).to eq({ 'two' => [1,2], 'three' => 3 })
- end
+ it 'should not change the original hashes' do
+ argument1 = { 'key1' => 'value1' }
+ original1 = argument1.dup
+ argument2 = { 'key2' => 'value2' }
+ original2 = argument2.dup
- it 'should not change the original hashes 3' do
- hash1 = {'one' => { 'two' => [1,2, {'two' => 2} ] } }
- hash2 = { 'one' => { 'three' => 3 } }
- hash = scope.function_deep_merge([hash1, hash2])
- expect(hash1).to eq({'one' => { 'two' => [1,2, {'two' => 2}] } })
- expect(hash2).to eq({ 'one' => { 'three' => 3 } })
- expect(hash['one']).to eq({ 'two' => [1,2, {'two' => 2} ], 'three' => 3 })
- expect(hash['one']['two']).to eq([1,2, {'two' => 2}])
- end
+ subject.call([argument1, argument2])
+ expect(argument1).to eq(original1)
+ expect(argument2).to eq(original2)
end
end
diff --git a/spec/functions/defined_with_params_spec.rb b/spec/functions/defined_with_params_spec.rb
index 3590304..e2f3abe 100755
--- a/spec/functions/defined_with_params_spec.rb
+++ b/spec/functions/defined_with_params_spec.rb
@@ -1,37 +1,35 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-require 'rspec-puppet'
describe 'defined_with_params' do
- describe 'when a resource is not specified' do
+ describe 'when no resource is specified' do
it { is_expected.to run.with_params().and_raise_error(ArgumentError) }
end
describe 'when compared against a resource with no attributes' do
let :pre_condition do
'user { "dan": }'
end
- it do
- is_expected.to run.with_params('User[dan]', {}).and_return(true)
- is_expected.to run.with_params('User[bob]', {}).and_return(false)
- is_expected.to run.with_params('User[dan]', {'foo' => 'bar'}).and_return(false)
- end
+ it { is_expected.to run.with_params('User[dan]', {}).and_return(true) }
+ it { is_expected.to run.with_params('User[bob]', {}).and_return(false) }
+ it { is_expected.to run.with_params('User[dan]', {'foo' => 'bar'}).and_return(false) }
end
describe 'when compared against a resource with attributes' do
let :pre_condition do
'user { "dan": ensure => present, shell => "/bin/csh", managehome => false}'
end
- it do
- is_expected.to run.with_params('User[dan]', {}).and_return(true)
- is_expected.to run.with_params('User[dan]', '').and_return(true)
- is_expected.to run.with_params('User[dan]', {'ensure' => 'present'}
- ).and_return(true)
- is_expected.to run.with_params('User[dan]',
- {'ensure' => 'present', 'managehome' => false}
- ).and_return(true)
- is_expected.to run.with_params('User[dan]',
- {'ensure' => 'absent', 'managehome' => false}
- ).and_return(false)
+ it { is_expected.to run.with_params('User[dan]', {}).and_return(true) }
+ it { is_expected.to run.with_params('User[dan]', '').and_return(true) }
+ it { is_expected.to run.with_params('User[dan]', {'ensure' => 'present'}).and_return(true) }
+ it { is_expected.to run.with_params('User[dan]', {'ensure' => 'present', 'managehome' => false}).and_return(true) }
+ it { is_expected.to run.with_params('User[dan]', {'ensure' => 'absent', 'managehome' => false}).and_return(false) }
+ end
+
+ describe 'when passing undef values' do
+ let :pre_condition do
+ 'file { "/tmp/a": ensure => present }'
end
+
+ it { is_expected.to run.with_params('File[/tmp/a]', {}).and_return(true) }
+ it { is_expected.to run.with_params('File[/tmp/a]', { 'ensure' => 'present', 'owner' => :undef }).and_return(true) }
end
end
diff --git a/spec/functions/delete_at_spec.rb b/spec/functions/delete_at_spec.rb
index 7c20aec..0e19472 100755
--- a/spec/functions/delete_at_spec.rb
+++ b/spec/functions/delete_at_spec.rb
@@ -1,25 +1,28 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the delete_at function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'delete_at' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one', 1).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(1, 1).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(['one'], 'two').and_raise_error(Puppet::ParseError) }
+ it {
+ pending("Current implementation ignores parameters after the first two.")
+ is_expected.to run.with_params(['one'], 0, 1).and_raise_error(Puppet::ParseError)
+ }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("delete_at")).to eq("function_delete_at")
+ describe 'argument validation' do
+ it { is_expected.to run.with_params([0, 1, 2], 3).and_raise_error(Puppet::ParseError) }
end
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_delete_at([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should delete an item at specified location from an array" do
- result = scope.function_delete_at([['a','b','c'],1])
- expect(result).to(eq(['a','c']))
- end
+ it { is_expected.to run.with_params([0, 1, 2], 1).and_return([0, 2]) }
+ it { is_expected.to run.with_params([0, 1, 2], -1).and_return([0, 1]) }
+ it { is_expected.to run.with_params([0, 1, 2], -4).and_return([0, 1, 2]) }
- it "should not change origin array passed as argument" do
- origin_array = ['a','b','c','d']
- result = scope.function_delete_at([origin_array, 1])
- expect(origin_array).to(eq(['a','b','c','d']))
+ it "should leave the original array intact" do
+ argument = [1, 2, 3]
+ original = argument.dup
+ result = subject.call([argument,2])
+ expect(argument).to eq(original)
end
end
diff --git a/spec/functions/delete_regex_spec.rb b/spec/functions/delete_regex_spec.rb
new file mode 100755
index 0000000..f27a946
--- /dev/null
+++ b/spec/functions/delete_regex_spec.rb
@@ -0,0 +1,54 @@
+require 'spec_helper'
+
+describe 'delete_regex' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([], 'two') }
+ it { is_expected.to run.with_params({}, 'two') }
+ it { is_expected.to run.with_params([], 'two', 'three').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([], 'two', 'three', 'four').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(1, 'two').and_raise_error(TypeError) }
+
+ describe 'deleting from an array' do
+ it { is_expected.to run.with_params([], '').and_return([]) }
+ it { is_expected.to run.with_params([], 'two').and_return([]) }
+ it { is_expected.to run.with_params(['two'], 'two').and_return([]) }
+ it { is_expected.to run.with_params(['two', 'two'], 'two').and_return([]) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], '^t.*').and_return(['one']) }
+ it { is_expected.to run.with_params(['ab', 'b', 'c', 'b'], 'b').and_return(['ab', 'c']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], 'four').and_return(['one', 'two', 'three']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], 'e').and_return(['one', 'two', 'three']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], 'two').and_return(['one', 'three']) }
+ it { is_expected.to run.with_params(['two', 'one', 'two', 'three', 'two'], 'two').and_return(['one', 'three']) }
+ it { is_expected.to run.with_params(['abracadabra'], 'abr').and_return(['abracadabra']) }
+ it { is_expected.to run.with_params(['abracadabra'], '^.*jimbob.*$').and_return(['abracadabra']) }
+ end
+
+ describe 'deleting from an array' do
+ it { is_expected.to run.with_params({}, '').and_return({}) }
+ it { is_expected.to run.with_params({}, 'key').and_return({}) }
+ it { is_expected.to run.with_params({'key' => 'value'}, 'key').and_return({}) }
+ it { is_expected.to run \
+ .with_params({'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'}, 'key2') \
+ .and_return( {'key1' => 'value1', 'key3' => 'value3'})
+ }
+ it { is_expected.to run \
+ .with_params({'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'}, ['key1', 'key2']) \
+ .and_return( {'key3' => 'value3'})
+ }
+ end
+
+ it "should leave the original array intact" do
+ argument1 = ['one','two','three']
+ original1 = argument1.dup
+ subject.call([argument1,'two'])
+ expect(argument1).to eq(original1)
+ end
+ it "should leave the original hash intact" do
+ argument1 = {'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'}
+ original1 = argument1.dup
+ subject.call([argument1,'key2'])
+ expect(argument1).to eq(original1)
+ end
+end
diff --git a/spec/functions/delete_spec.rb b/spec/functions/delete_spec.rb
index c8edd78..b44accf 100755
--- a/spec/functions/delete_spec.rb
+++ b/spec/functions/delete_spec.rb
@@ -1,61 +1,70 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the delete function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'delete' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([], 'two') }
+ it { is_expected.to run.with_params([], 'two', 'three').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(1, 'two').and_raise_error(TypeError) }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("delete")).to eq("function_delete")
+ describe 'deleting from an array' do
+ it { is_expected.to run.with_params([], '').and_return([]) }
+ it { is_expected.to run.with_params([], 'two').and_return([]) }
+ it { is_expected.to run.with_params(['two'], 'two').and_return([]) }
+ it { is_expected.to run.with_params(['two', 'two'], 'two').and_return([]) }
+ it { is_expected.to run.with_params(['ab', 'b', 'c', 'b'], 'b').and_return(['ab', 'c']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], 'four').and_return(['one', 'two', 'three']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], 'e').and_return(['one', 'two', 'three']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], 'two').and_return(['one', 'three']) }
+ it { is_expected.to run.with_params(['two', 'one', 'two', 'three', 'two'], 'two').and_return(['one', 'three']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three', 'two'], ['one', 'two']).and_return(['three']) }
end
- it "should raise a ParseError if there are fewer than 2 arguments" do
- expect { scope.function_delete([]) }.to(raise_error(Puppet::ParseError))
+ describe 'deleting from a string' do
+ it { is_expected.to run.with_params('', '').and_return('') }
+ it { is_expected.to run.with_params('bar', '').and_return('bar') }
+ it { is_expected.to run.with_params('', 'bar').and_return('') }
+ it { is_expected.to run.with_params('bar', 'bar').and_return('') }
+ it { is_expected.to run.with_params('barbar', 'bar').and_return('') }
+ it { is_expected.to run.with_params('barfoobar', 'bar').and_return('foo') }
+ it { is_expected.to run.with_params('foobarbabarz', 'bar').and_return('foobaz') }
+ it { is_expected.to run.with_params('foobarbabarz', ['foo', 'bar']).and_return('baz') }
+ # this is so sick
+ it { is_expected.to run.with_params('barfoobar', ['barbar', 'foo']).and_return('barbar') }
+ it { is_expected.to run.with_params('barfoobar', ['foo', 'barbar']).and_return('') }
end
- it "should raise a ParseError if there are greater than 2 arguments" do
- expect { scope.function_delete([[], 'foo', 'bar']) }.to(raise_error(Puppet::ParseError))
+ describe 'deleting from an array' do
+ it { is_expected.to run.with_params({}, '').and_return({}) }
+ it { is_expected.to run.with_params({}, 'key').and_return({}) }
+ it { is_expected.to run.with_params({'key' => 'value'}, 'key').and_return({}) }
+ it { is_expected.to run \
+ .with_params({'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'}, 'key2') \
+ .and_return( {'key1' => 'value1', 'key3' => 'value3'})
+ }
+ it { is_expected.to run \
+ .with_params({'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'}, ['key1', 'key2']) \
+ .and_return( {'key3' => 'value3'})
+ }
end
- it "should raise a TypeError if a number is passed as the first argument" do
- expect { scope.function_delete([1, 'bar']) }.to(raise_error(TypeError))
+ it "should leave the original array intact" do
+ argument1 = ['one','two','three']
+ original1 = argument1.dup
+ result = subject.call([argument1,'two'])
+ expect(argument1).to eq(original1)
end
-
- it "should delete all instances of an element from an array" do
- result = scope.function_delete([['a', 'b', 'c', 'b'], 'b'])
- expect(result).to(eq(['a', 'c']))
- end
-
- it "should delete all instances of a substring from a string" do
- result = scope.function_delete(['foobarbabarz', 'bar'])
- expect(result).to(eq('foobaz'))
+ it "should leave the original string intact" do
+ argument1 = 'onetwothree'
+ original1 = argument1.dup
+ result = subject.call([argument1,'two'])
+ expect(argument1).to eq(original1)
end
-
- it "should delete a key from a hash" do
- result = scope.function_delete([{'a' => 1, 'b' => 2, 'c' => 3}, 'b'])
- expect(result).to(eq({'a' => 1, 'c' => 3}))
+ it "should leave the original hash intact" do
+ argument1 = {'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'}
+ original1 = argument1.dup
+ result = subject.call([argument1,'key2'])
+ expect(argument1).to eq(original1)
end
-
- it 'should accept an array of items to delete' do
- result = scope.function_delete([{'a' => 1, 'b' => 2, 'c' => 3}, ['b', 'c']])
- expect(result).to(eq({'a' => 1}))
- end
-
- it "should not change origin array passed as argument" do
- origin_array = ['a', 'b', 'c', 'd']
- result = scope.function_delete([origin_array, 'b'])
- expect(origin_array).to(eq(['a', 'b', 'c', 'd']))
- end
-
- it "should not change the origin string passed as argument" do
- origin_string = 'foobarbabarz'
- result = scope.function_delete([origin_string, 'bar'])
- expect(origin_string).to(eq('foobarbabarz'))
- end
-
- it "should not change origin hash passed as argument" do
- origin_hash = {'a' => 1, 'b' => 2, 'c' => 3}
- result = scope.function_delete([origin_hash, 'b'])
- expect(origin_hash).to(eq({'a' => 1, 'b' => 2, 'c' => 3}))
- end
-
end
diff --git a/spec/functions/delete_undef_values_spec.rb b/spec/functions/delete_undef_values_spec.rb
index dc67953..ec9fb9c 100755
--- a/spec/functions/delete_undef_values_spec.rb
+++ b/spec/functions/delete_undef_values_spec.rb
@@ -1,41 +1,56 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the delete_undef_values function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("delete_undef_values")).to eq("function_delete_undef_values")
- end
-
- it "should raise a ParseError if there is less than 1 argument" do
- expect { scope.function_delete_undef_values([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should raise a ParseError if the argument is not Array nor Hash" do
- expect { scope.function_delete_undef_values(['']) }.to( raise_error(Puppet::ParseError))
- expect { scope.function_delete_undef_values([nil]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should delete all undef items from Array and only these" do
- result = scope.function_delete_undef_values([['a',:undef,'c','undef']])
- expect(result).to(eq(['a','c','undef']))
- end
-
- it "should delete all undef items from Hash and only these" do
- result = scope.function_delete_undef_values([{'a'=>'A','b'=>:undef,'c'=>'C','d'=>'undef'}])
- expect(result).to(eq({'a'=>'A','c'=>'C','d'=>'undef'}))
- end
-
- it "should not change origin array passed as argument" do
- origin_array = ['a',:undef,'c','undef']
- result = scope.function_delete_undef_values([origin_array])
- expect(origin_array).to(eq(['a',:undef,'c','undef']))
+describe 'delete_undef_values' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError) }
+
+ describe 'when deleting from an array' do
+ [ :undef, '', nil ].each do |undef_value|
+ describe "when undef is represented by #{undef_value.inspect}" do
+ before do
+ pending("review behaviour when being passed undef as #{undef_value.inspect}") if undef_value == ''
+ pending("review behaviour when being passed undef as #{undef_value.inspect}") if undef_value == nil
+ end
+ it { is_expected.to run.with_params([undef_value]).and_return([]) }
+ it { is_expected.to run.with_params(['one',undef_value,'two','three']).and_return(['one','two','three']) }
+ end
+
+ it "should leave the original argument intact" do
+ argument = ['one',undef_value,'two']
+ original = argument.dup
+ result = subject.call([argument,2])
+ expect(argument).to eq(original)
+ end
+ end
+
+ it { is_expected.to run.with_params(['undef']).and_return(['undef']) }
end
- it "should not change origin hash passed as argument" do
- origin_hash = { 'a' => 1, 'b' => :undef, 'c' => 'undef' }
- result = scope.function_delete_undef_values([origin_hash])
- expect(origin_hash).to(eq({ 'a' => 1, 'b' => :undef, 'c' => 'undef' }))
+ describe 'when deleting from a hash' do
+ [ :undef, '', nil ].each do |undef_value|
+ describe "when undef is represented by #{undef_value.inspect}" do
+ before do
+ pending("review behaviour when being passed undef as #{undef_value.inspect}") if undef_value == ''
+ pending("review behaviour when being passed undef as #{undef_value.inspect}") if undef_value == nil
+ end
+ it { is_expected.to run.with_params({'key' => undef_value}).and_return({}) }
+ it { is_expected.to run \
+ .with_params({'key1' => 'value1', 'undef_key' => undef_value, 'key2' => 'value2'}) \
+ .and_return({'key1' => 'value1', 'key2' => 'value2'})
+ }
+ end
+
+ it "should leave the original argument intact" do
+ argument = { 'key1' => 'value1', 'key2' => undef_value }
+ original = argument.dup
+ result = subject.call([argument,2])
+ expect(argument).to eq(original)
+ end
+ end
+
+ it { is_expected.to run.with_params({'key' => 'undef'}).and_return({'key' => 'undef'}) }
end
end
diff --git a/spec/functions/delete_values_spec.rb b/spec/functions/delete_values_spec.rb
index 4f4d411..12907d4 100755
--- a/spec/functions/delete_values_spec.rb
+++ b/spec/functions/delete_values_spec.rb
@@ -1,36 +1,37 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the delete_values function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("delete_values")).to eq("function_delete_values")
- end
-
- it "should raise a ParseError if there are fewer than 2 arguments" do
- expect { scope.function_delete_values([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should raise a ParseError if there are greater than 2 arguments" do
- expect { scope.function_delete_values([[], 'foo', 'bar']) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should raise a TypeError if the argument is not a hash" do
- expect { scope.function_delete_values([1,'bar']) }.to( raise_error(TypeError))
- expect { scope.function_delete_values(['foo','bar']) }.to( raise_error(TypeError))
- expect { scope.function_delete_values([[],'bar']) }.to( raise_error(TypeError))
+describe 'delete_values' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one', 'two', 'three').and_raise_error(Puppet::ParseError) }
+ describe 'when the first argument is not a hash' do
+ it { is_expected.to run.with_params(1, 'two').and_raise_error(TypeError) }
+ it { is_expected.to run.with_params('one', 'two').and_raise_error(TypeError) }
+ it { is_expected.to run.with_params([], 'two').and_raise_error(TypeError) }
end
- it "should delete all instances of a value from a hash" do
- result = scope.function_delete_values([{ 'a'=>'A', 'b'=>'B', 'B'=>'C', 'd'=>'B' },'B'])
- expect(result).to(eq({ 'a'=>'A', 'B'=>'C' }))
+ describe 'when deleting from a hash' do
+ it { is_expected.to run.with_params({}, 'value').and_return({}) }
+ it { is_expected.to run \
+ .with_params({'key1' => 'value1'}, 'non-existing value') \
+ .and_return({'key1' => 'value1'})
+ }
+ it { is_expected.to run \
+ .with_params({'key1' => 'value1', 'key2' => 'value to delete'}, 'value to delete') \
+ .and_return({'key1' => 'value1'})
+ }
+ it { is_expected.to run \
+ .with_params({'key1' => 'value1', 'key2' => 'value to delete', 'key3' => 'value to delete'}, 'value to delete') \
+ .and_return({'key1' => 'value1'})
+ }
end
- it "should not change origin hash passed as argument" do
- origin_hash = { 'a' => 1, 'b' => 2, 'c' => 3 }
- result = scope.function_delete_values([origin_hash, 2])
- expect(origin_hash).to(eq({ 'a' => 1, 'b' => 2, 'c' => 3 }))
+ it "should leave the original argument intact" do
+ argument = { 'key1' => 'value1', 'key2' => 'value2' }
+ original = argument.dup
+ result = subject.call([argument, 'value2'])
+ expect(argument).to eq(original)
end
-
end
diff --git a/spec/functions/deprecation_spec.rb b/spec/functions/deprecation_spec.rb
new file mode 100644
index 0000000..cee4f1c
--- /dev/null
+++ b/spec/functions/deprecation_spec.rb
@@ -0,0 +1,60 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.0
+ describe 'deprecation' do
+ before(:each) {
+ # this is to reset the strict variable to default
+ Puppet.settings[:strict] = :warning
+ }
+
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(ArgumentError) }
+
+ it 'should display a single warning' do
+ Puppet.expects(:warning).with(includes('heelo'))
+ is_expected.to run.with_params('key', 'heelo')
+ end
+
+ it 'should display a single warning, despite multiple calls' do
+ Puppet.expects(:warning).with(includes('heelo')).once
+ is_expected.to run.with_params('key', 'heelo')
+ is_expected.to run.with_params('key', 'heelo')
+ end
+
+ it 'should fail twice with message, with multiple calls. when strict= :error' do
+ Puppet.settings[:strict] = :error
+ Puppet.expects(:warning).with(includes('heelo')).never
+ is_expected.to run.with_params('key', 'heelo').and_raise_error(RuntimeError, /deprecation. key. heelo/)
+ is_expected.to run.with_params('key', 'heelo').and_raise_error(RuntimeError, /deprecation. key. heelo/)
+ end
+
+ it 'should display nothing, despite multiple calls. strict= :off' do
+ Puppet.settings[:strict] = :off
+ Puppet.expects(:warning).with(includes('heelo')).never
+ is_expected.to run.with_params('key', 'heelo')
+ is_expected.to run.with_params('key', 'heelo')
+ end
+
+ after(:all) {
+ # this is to reset the strict variable to default
+ Puppet.settings[:strict] = :warning
+ }
+ end
+else
+ # Puppet version < 4 will use these tests.
+ describe 'deprecation' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
+ before(:all) do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ end
+ 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 'should display a single warning' do
+ scope.expects(:warning).with(includes('heelo'))
+ is_expected.to run.with_params('key', 'heelo')
+ end
+ end
+end
diff --git a/spec/functions/difference_spec.rb b/spec/functions/difference_spec.rb
index 24b2b1b..d5e983d 100755
--- a/spec/functions/difference_spec.rb
+++ b/spec/functions/difference_spec.rb
@@ -1,19 +1,21 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the difference function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("difference")).to eq("function_difference")
- end
-
- it "should raise a ParseError if there are fewer than 2 arguments" do
- expect { scope.function_difference([]) }.to( raise_error(Puppet::ParseError) )
- end
-
- it "should return the difference between two arrays" do
- result = scope.function_difference([["a","b","c"],["b","c","d"]])
- expect(result).to(eq(["a"]))
- end
+describe 'difference' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one', 'two', 'three').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one', []).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([], 'two').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params({}, {}).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([], []).and_return([]) }
+ it { is_expected.to run.with_params([], ['one']).and_return([]) }
+ it { is_expected.to run.with_params(['one'], ['one']).and_return([]) }
+ it { is_expected.to run.with_params(['one'], []).and_return(['one']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'three']).and_return(['one']) }
+ it { is_expected.to run.with_params(['one', 'two', 'two', 'three'], ['two', 'three']).and_return(['one']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'two', 'three']).and_return(['one']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'three', 'four']).and_return(['one']) }
+ it 'should not confuse types' do is_expected.to run.with_params(['1', '2', '3'], [1, 2]).and_return(['1', '2', '3']) end
end
diff --git a/spec/functions/dig44_spec.rb b/spec/functions/dig44_spec.rb
new file mode 100644
index 0000000..4f7408d
--- /dev/null
+++ b/spec/functions/dig44_spec.rb
@@ -0,0 +1,105 @@
+require 'spec_helper'
+
+describe 'dig44' do
+
+ let(:data) do
+ {
+ 'a' => {
+ 'g' => '2',
+ 'e' => [
+ 'f0',
+ 'f1',
+ {
+ 'x' => {
+ 'y' => 'z'
+ }
+ },
+ 'f3',
+ ]
+ },
+ 'b' => true,
+ 'c' => false,
+ 'd' => '1',
+ 'e' => :undef,
+ 'f' => nil,
+ }
+ end
+
+ context 'single values' do
+ it 'should exist' do
+ is_expected.not_to be_nil
+ end
+
+ it 'should require two arguments' do
+ is_expected.to run.with_params().and_raise_error(ArgumentError)
+ end
+
+ it 'should fail if the data is not a structure' do
+ is_expected.to run.with_params('test', []).and_raise_error(Puppet::Error)
+ end
+
+ it 'should fail if the path is not an array' do
+ is_expected.to run.with_params({}, '').and_raise_error(Puppet::Error)
+ end
+
+ it 'should return the value if the value is string' do
+ is_expected.to run.with_params(data, ['d'], 'default').and_return('1')
+ end
+
+ it 'should return true if the value is true' do
+ is_expected.to run.with_params(data, ['b'], 'default').and_return(true)
+ end
+
+ it 'should return false if the value is false' do
+ is_expected.to run.with_params(data, ['c'], 'default').and_return(false)
+ end
+
+ it 'should return the default if the value is nil' do
+ is_expected.to run.with_params(data, ['f'], 'default').and_return('default')
+ end
+
+ it 'should return the default if the value is :undef (same as nil)' do
+ is_expected.to run.with_params(data, ['e'], 'default').and_return('default')
+ end
+
+ it 'should return the default if the path is not found' do
+ is_expected.to run.with_params(data, ['missing'], 'default').and_return('default')
+ end
+ end
+
+ context 'structure values' do
+
+ it 'should be able to extract a deeply nested hash value' do
+ is_expected.to run.with_params(data, %w(a g), 'default').and_return('2')
+ end
+
+ it 'should return the default value if the path is too long' do
+ is_expected.to run.with_params(data, %w(a g c d), 'default').and_return('default')
+ end
+
+ it 'should support an array index (number) in the path' do
+ is_expected.to run.with_params(data, ['a', 'e', 1], 'default').and_return('f1')
+ end
+
+ it 'should support an array index (string) in the path' do
+ is_expected.to run.with_params(data, %w(a e 1), 'default').and_return('f1')
+ end
+
+ it 'should return the default value if an array index is not a number' do
+ is_expected.to run.with_params(data, %w(a b c), 'default').and_return('default')
+ end
+
+ it 'should return the default value if and index is out of array length' do
+ is_expected.to run.with_params(data, %w(a e 5), 'default').and_return('default')
+ end
+
+ it 'should be able to path though both arrays and hashes' do
+ is_expected.to run.with_params(data, %w(a e 2 x y), 'default').and_return('z')
+ end
+
+ it 'should return "nil" if value is not found and no default value is provided' do
+ is_expected.to run.with_params(data, %w(a 1)).and_return(nil)
+ end
+
+ end
+end
diff --git a/spec/functions/dig_spec.rb b/spec/functions/dig_spec.rb
new file mode 100644
index 0000000..ad16fdd
--- /dev/null
+++ b/spec/functions/dig_spec.rb
@@ -0,0 +1,13 @@
+require 'spec_helper'
+
+describe 'dig' do
+
+ it "should exist" do
+ expect(Puppet::Parser::Functions.function("dig")).to eq("function_dig")
+ end
+
+ it "should give a deprecation warning when called" do
+ scope.expects(:warning).with("dig() DEPRECATED: This function has been replaced in Puppet 4.5.0, please use dig44() for backwards compatibility or use the new version.")
+ scope.function_dig([{}, []])
+ end
+end
diff --git a/spec/functions/dirname_spec.rb b/spec/functions/dirname_spec.rb
index 8a3bcab..46c4c35 100755
--- a/spec/functions/dirname_spec.rb
+++ b/spec/functions/dirname_spec.rb
@@ -1,24 +1,13 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the dirname function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("dirname")).to eq("function_dirname")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_dirname([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return dirname for an absolute path" do
- result = scope.function_dirname(['/path/to/a/file.ext'])
- expect(result).to(eq('/path/to/a'))
- end
-
- it "should return dirname for a relative path" do
- result = scope.function_dirname(['path/to/a/file.ext'])
- expect(result).to(eq('path/to/a'))
- end
+describe 'dirname' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('/path/to/a/file.ext', []).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('/path/to/a/file.ext').and_return('/path/to/a') }
+ it { is_expected.to run.with_params('relative_path/to/a/file.ext').and_return('relative_path/to/a') }
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/downcase_spec.rb b/spec/functions/downcase_spec.rb
index edebc44..c594560 100755
--- a/spec/functions/downcase_spec.rb
+++ b/spec/functions/downcase_spec.rb
@@ -1,33 +1,15 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the downcase function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("downcase")).to eq("function_downcase")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_downcase([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should downcase a string" do
- result = scope.function_downcase(["ASFD"])
- expect(result).to(eq("asfd"))
- end
-
- it "should do nothing to a string that is already downcase" do
- result = scope.function_downcase(["asdf asdf"])
- expect(result).to(eq("asdf asdf"))
- end
-
- it "should accept objects which extend String" do
- class AlsoString < String
- end
-
- value = AlsoString.new("ASFD")
- result = scope.function_downcase([value])
- result.should(eq('asfd'))
- end
+describe 'downcase' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(100).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params("abc").and_return("abc") }
+ it { is_expected.to run.with_params("Abc").and_return("abc") }
+ it { is_expected.to run.with_params("ABC").and_return("abc") }
+
+ it { is_expected.to run.with_params(AlsoString.new("ABC")).and_return("abc") }
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(["ONE", "TWO"]).and_return(["one", "two"]) }
+ it { is_expected.to run.with_params(["One", 1, "Two"]).and_return(["one", 1, "two"]) }
end
diff --git a/spec/functions/empty_spec.rb b/spec/functions/empty_spec.rb
index 6a97c4c..a3a25d6 100755
--- a/spec/functions/empty_spec.rb
+++ b/spec/functions/empty_spec.rb
@@ -1,32 +1,22 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the empty function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("empty")).to eq("function_empty")
- end
+describe 'empty' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError)
+ }
+ it { is_expected.to run.with_params(0).and_return(false) }
+ it { is_expected.to run.with_params('').and_return(true) }
+ it { is_expected.to run.with_params('one').and_return(false) }
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_empty([]) }.to( raise_error(Puppet::ParseError))
- end
+ it { is_expected.to run.with_params(AlsoString.new('')).and_return(true) }
+ it { is_expected.to run.with_params(AlsoString.new('one')).and_return(false) }
- it "should return a true for an empty string" do
- result = scope.function_empty([''])
- expect(result).to(eq(true))
- end
+ it { is_expected.to run.with_params([]).and_return(true) }
+ it { is_expected.to run.with_params(['one']).and_return(false) }
- it "should return a false for a non-empty string" do
- result = scope.function_empty(['asdf'])
- expect(result).to(eq(false))
- end
-
- it "should accept objects which extend String" do
- class AlsoString < String
- end
-
- value = AlsoString.new()
- result = scope.function_empty([value])
- result.should(eq(true))
- end
+ it { is_expected.to run.with_params({}).and_return(true) }
+ it { is_expected.to run.with_params({'key' => 'value'}).and_return(false) }
end
diff --git a/spec/functions/ensure_packages_spec.rb b/spec/functions/ensure_packages_spec.rb
index 436be10..5d97684 100755
--- a/spec/functions/ensure_packages_spec.rb
+++ b/spec/functions/ensure_packages_spec.rb
@@ -1,81 +1,44 @@
-#! /usr/bin/env ruby
-
require 'spec_helper'
-require 'rspec-puppet'
-require 'puppet_spec/compiler'
describe 'ensure_packages' do
- include PuppetSpec::Compiler
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it {
+ pending("should not accept numbers as arguments")
+ is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError)
+ }
+ it {
+ pending("should not accept numbers as arguments")
+ is_expected.to run.with_params(["packagename", 1]).and_raise_error(Puppet::ParseError)
+ }
+ it { is_expected.to run.with_params("packagename") }
+ it { is_expected.to run.with_params(["packagename1", "packagename2"]) }
- before :each do
- Puppet::Parser::Functions.autoloader.loadall
- Puppet::Parser::Functions.function(:ensure_packages)
- Puppet::Parser::Functions.function(:ensure_resource)
- Puppet::Parser::Functions.function(:defined_with_params)
- Puppet::Parser::Functions.function(:create_resources)
- end
+ context 'given a catalog with "package { puppet: ensure => absent }"' do
+ let(:pre_condition) { 'package { puppet: ensure => absent }' }
- let :node do Puppet::Node.new('localhost') end
- let :compiler do Puppet::Parser::Compiler.new(node) end
- let :scope do
- if Puppet.version.to_f >= 3.0
- Puppet::Parser::Scope.new(compiler)
- else
- newscope = Puppet::Parser::Scope.new
- newscope.compiler = compiler
- newscope.source = Puppet::Resource::Type.new(:node, :localhost)
- newscope
- end
- end
+ describe 'after running ensure_package("facter")' do
+ before { subject.call(['facter']) }
- describe 'argument handling' do
- it 'fails with no arguments' do
- expect {
- scope.function_ensure_packages([])
- }.to raise_error(Puppet::ParseError, /0 for 1 or 2/)
+ # this lambda is required due to strangeness within rspec-puppet's expectation handling
+ it { expect(lambda { catalogue }).to contain_package('puppet').with_ensure('absent') }
+ it { expect(lambda { catalogue }).to contain_package('facter').with_ensure('present') }
end
- it 'accepts an array of values' do
- scope.function_ensure_packages([['foo']])
- end
+ describe 'after running ensure_package("facter", { "provider" => "gem" })' do
+ before { subject.call(['facter', { "provider" => "gem" }]) }
- it 'accepts a single package name as a string' do
- scope.function_ensure_packages(['foo'])
+ # this lambda is required due to strangeness within rspec-puppet's expectation handling
+ it { expect(lambda { catalogue }).to contain_package('puppet').with_ensure('absent').without_provider() }
+ it { expect(lambda { catalogue }).to contain_package('facter').with_ensure('present').with_provider("gem") }
end
end
- context 'given a catalog with puppet package => absent' do
- let :catalog do
- compile_to_catalog(<<-EOS
- ensure_packages(['facter'])
- package { puppet: ensure => absent }
- EOS
- )
- end
-
- it 'has no effect on Package[puppet]' do
- expect(catalog.resource(:package, 'puppet')['ensure']).to eq('absent')
- end
- end
+ context 'given hash of packages' do
+ before { subject.call([{"foo" => { "provider" => "rpm" }, "bar" => { "provider" => "gem" }}, { "ensure" => "present"}]) }
- context 'given a clean catalog' do
- let :catalog do
- compile_to_catalog('ensure_packages(["facter"])')
- end
-
- it 'declares package resources with ensure => present' do
- expect(catalog.resource(:package, 'facter')['ensure']).to eq('present')
- end
- end
-
- context 'given a clean catalog and specified defaults' do
- let :catalog do
- compile_to_catalog('ensure_packages(["facter"], {"provider" => "gem"})')
- end
-
- it 'declares package resources with ensure => present' do
- expect(catalog.resource(:package, 'facter')['ensure']).to eq('present')
- expect(catalog.resource(:package, 'facter')['provider']).to eq('gem')
- end
+ # this lambda is required due to strangeness within rspec-puppet's expectation handling
+ it { expect(lambda { catalogue }).to contain_package('foo').with({'provider' => 'rpm', 'ensure' => 'present'}) }
+ it { expect(lambda { catalogue }).to contain_package('bar').with({'provider' => 'gem', 'ensure' => 'present'}) }
end
end
diff --git a/spec/functions/ensure_resource_spec.rb b/spec/functions/ensure_resource_spec.rb
index 33bcac0..d552f4e 100755
--- a/spec/functions/ensure_resource_spec.rb
+++ b/spec/functions/ensure_resource_spec.rb
@@ -1,113 +1,93 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-require 'rspec-puppet'
-require 'puppet_spec/compiler'
describe 'ensure_resource' do
- include PuppetSpec::Compiler
-
- before :all do
- Puppet::Parser::Functions.autoloader.loadall
- Puppet::Parser::Functions.function(:ensure_packages)
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(ArgumentError, /Must specify a type/) }
+ it { is_expected.to run.with_params('type').and_raise_error(ArgumentError, /Must specify a title/) }
+ if Puppet.version.to_f >= 4.6
+ it { is_expected.to run.with_params('type', 'title', {}, 'extras').and_raise_error(ArgumentError) }
+ else
+ it { is_expected.to run.with_params('type', 'title', {}, 'extras').and_raise_error(Puppet::ParseError) }
end
- let :node do Puppet::Node.new('localhost') end
- let :compiler do Puppet::Parser::Compiler.new(node) end
- let :scope do Puppet::Parser::Scope.new(compiler) end
+ it {
+ pending("should not accept numbers as arguments")
+ is_expected.to run.with_params(1,2,3).and_raise_error(Puppet::ParseError)
+ }
- describe 'when a type or title is not specified' do
- it { expect { scope.function_ensure_resource([]) }.to raise_error }
- it { expect { scope.function_ensure_resource(['type']) }.to raise_error }
- end
+ context 'given an empty catalog' do
+ describe 'after running ensure_resource("user", "username1", {})' do
+ before { subject.call(['User', 'username1', {}]) }
- describe 'when compared against a resource with no attributes' do
- let :catalog do
- compile_to_catalog(<<-EOS
- user { "dan": }
- ensure_resource('user', 'dan', {})
- EOS
- )
+ # this lambda is required due to strangeness within rspec-puppet's expectation handling
+ it { expect(lambda { catalogue }).to contain_user('username1').without_ensure }
end
- it 'should contain the the ensured resources' do
- expect(catalog.resource(:user, 'dan').to_s).to eq('User[dan]')
+ describe 'after running ensure_resource("user", "username1", { gid => undef })' do
+ before { subject.call(['User', 'username1', { 'gid' => :undef }]) }
+
+ # this lambda is required due to strangeness within rspec-puppet's expectation handling
+ it { expect(lambda { catalogue }).to contain_user('username1').without_ensure }
+ it { expect(lambda { catalogue }).to contain_user('username1').without_gid }
end
- end
- describe 'works when compared against a resource with non-conflicting attributes' do
- [
- "ensure_resource('User', 'dan', {})",
- "ensure_resource('User', 'dan', '')",
- "ensure_resource('User', 'dan', {'ensure' => 'present'})",
- "ensure_resource('User', 'dan', {'ensure' => 'present', 'managehome' => false})"
- ].each do |ensure_resource|
- pp = <<-EOS
- user { "dan": ensure => present, shell => "/bin/csh", managehome => false}
- #{ensure_resource}
- EOS
-
- it { expect { compile_to_catalog(pp) }.to_not raise_error }
+ describe 'after running ensure_resource("user", "username1", { ensure => present, gid => undef })' do
+ before { subject.call(['User', 'username1', { 'ensure' => 'present', 'gid' => :undef }]) }
+
+ # this lambda is required due to strangeness within rspec-puppet's expectation handling
+ it { expect(lambda { catalogue }).to contain_user('username1').with_ensure('present') }
+ it { expect(lambda { catalogue }).to contain_user('username1').without_gid }
end
+
end
- describe 'fails when compared against a resource with conflicting attributes' do
- pp = <<-EOS
- user { "dan": ensure => present, shell => "/bin/csh", managehome => false}
- ensure_resource('User', 'dan', {'ensure' => 'absent', 'managehome' => false})
- EOS
+ context 'given a catalog with "user { username1: ensure => present }"' do
+ let(:pre_condition) { 'user { username1: ensure => present }' }
- it { expect { compile_to_catalog(pp) }.to raise_error }
- end
+ describe 'after running ensure_resource("user", "username1", {})' do
+ before { subject.call(['User', 'username1', {}]) }
- describe 'when an array of new resources are passed in' do
- let :catalog do
- compile_to_catalog("ensure_resource('User', ['dan', 'alex'], {})")
+ # this lambda is required due to strangeness within rspec-puppet's expectation handling
+ it { expect(lambda { catalogue }).to contain_user('username1').with_ensure('present') }
end
- it 'should contain the ensured resources' do
- expect(catalog.resource('User[dan]').to_s).to eq('User[dan]')
- expect(catalog.resource('User[alex]').to_s).to eq('User[alex]')
+ describe 'after running ensure_resource("user", "username2", {})' do
+ before { subject.call(['User', 'username2', {}]) }
+
+ # this lambda is required due to strangeness within rspec-puppet's expectation handling
+ it { expect(lambda { catalogue }).to contain_user('username1').with_ensure('present') }
+ it { expect(lambda { catalogue }).to contain_user('username2').without_ensure }
end
- end
- describe 'when an array of existing resources is compared against existing resources' do
- pp = <<-EOS
- user { 'dan': ensure => present; 'alex': ensure => present }
- ensure_resource('User', ['dan', 'alex'], {})
- EOS
+ describe 'after running ensure_resource("user", "username1", { gid => undef })' do
+ before { subject.call(['User', 'username1', { 'gid' => :undef }]) }
- let :catalog do
- compile_to_catalog(pp)
+ # this lambda is required due to strangeness within rspec-puppet's expectation handling
+ it { expect(lambda { catalogue }).to contain_user('username1').with_ensure('present') }
end
- it 'should return the existing resources' do
- expect(catalog.resource('User[dan]').to_s).to eq('User[dan]')
- expect(catalog.resource('User[alex]').to_s).to eq('User[alex]')
- end
- end
+ describe 'after running ensure_resource("user", ["username1", "username2"], {})' do
+ before { subject.call(['User', ['username1', 'username2'], {}]) }
- describe 'works when compared against existing resources with attributes' do
- [
- "ensure_resource('User', ['dan', 'alex'], {})",
- "ensure_resource('User', ['dan', 'alex'], '')",
- "ensure_resource('User', ['dan', 'alex'], {'ensure' => 'present'})",
- ].each do |ensure_resource|
- pp = <<-EOS
- user { 'dan': ensure => present; 'alex': ensure => present }
- #{ensure_resource}
- EOS
-
- it { expect { compile_to_catalog(pp) }.to_not raise_error }
+ # this lambda is required due to strangeness within rspec-puppet's expectation handling
+ it { expect(lambda { catalogue }).to contain_user('username1').with_ensure('present') }
+ it { expect(lambda { catalogue }).to contain_user('username2').without_ensure }
end
- end
- describe 'fails when compared against existing resources with conflicting attributes' do
- pp = <<-EOS
- user { 'dan': ensure => present; 'alex': ensure => present }
- ensure_resource('User', ['dan', 'alex'], {'ensure' => 'absent'})
- EOS
+ describe 'when providing already set params' do
+ let(:params) { { 'ensure' => 'present' } }
+ before { subject.call(['User', ['username2', 'username3'], params]) }
- it { expect { compile_to_catalog(pp) }.to raise_error }
- end
+ # this lambda is required due to strangeness within rspec-puppet's expectation handling
+ it { expect(lambda { catalogue }).to contain_user('username1').with(params) }
+ it { expect(lambda { catalogue }).to contain_user('username2').with(params) }
+ end
+ context 'when trying to add params' do
+ it { is_expected.to run \
+ .with_params('User', 'username1', { 'ensure' => 'present', 'shell' => true }) \
+ .and_raise_error(Puppet::Resource::Catalog::DuplicateResourceError, /User\[username1\] is already declared/)
+ }
+ end
+ end
end
diff --git a/spec/functions/flatten_spec.rb b/spec/functions/flatten_spec.rb
index de8c66d..a4338be 100755
--- a/spec/functions/flatten_spec.rb
+++ b/spec/functions/flatten_spec.rb
@@ -1,27 +1,14 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the flatten function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("flatten")).to eq("function_flatten")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_flatten([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should raise a ParseError if there is more than 1 argument" do
- expect { scope.function_flatten([[], []]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should flatten a complex data structure" do
- result = scope.function_flatten([["a","b",["c",["d","e"],"f","g"]]])
- expect(result).to(eq(["a","b","c","d","e","f","g"]))
- end
-
- it "should do nothing to a structure that is already flat" do
- result = scope.function_flatten([["a","b","c","d"]])
- expect(result).to(eq(["a","b","c","d"]))
- end
+describe 'flatten' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([], []).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(['one']).and_return(['one']) }
+ it { is_expected.to run.with_params([['one']]).and_return(['one']) }
+ it { is_expected.to run.with_params(["a","b","c","d","e","f","g"]).and_return(["a","b","c","d","e","f","g"]) }
+ it { is_expected.to run.with_params([["a","b",["c",["d","e"],"f","g"]]]).and_return(["a","b","c","d","e","f","g"]) }
end
diff --git a/spec/functions/floor_spec.rb b/spec/functions/floor_spec.rb
index 12a6917..608c602 100755
--- a/spec/functions/floor_spec.rb
+++ b/spec/functions/floor_spec.rb
@@ -1,39 +1,12 @@
-#! /usr/bin/env ruby -S rspec
-
require 'spec_helper'
-describe "the floor function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("floor")).to eq("function_floor")
- end
-
- it "should raise a ParseError if there is less than 1 argument" do
- expect { scope.function_floor([]) }.to( raise_error(Puppet::ParseError, /Wrong number of arguments/))
- end
-
- it "should should raise a ParseError if input isn't numeric (eg. String)" do
- expect { scope.function_floor(["foo"]) }.to( raise_error(Puppet::ParseError, /Wrong argument type/))
- end
-
- it "should should raise a ParseError if input isn't numeric (eg. Boolean)" do
- expect { scope.function_floor([true]) }.to( raise_error(Puppet::ParseError, /Wrong argument type/))
- end
-
- it "should return an integer when a numeric type is passed" do
- result = scope.function_floor([12.4])
- expect(result.is_a?(Integer)).to(eq(true))
- end
-
- it "should return the input when an integer is passed" do
- result = scope.function_floor([7])
- expect(result).to(eq(7))
- end
-
- it "should return the largest integer less than or equal to the input" do
- result = scope.function_floor([3.8])
- expect(result).to(eq(3))
- end
+describe 'floor' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params("foo").and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params(34).and_return(34) }
+ it { is_expected.to run.with_params(-34).and_return(-34) }
+ it { is_expected.to run.with_params(33.1).and_return(33) }
+ it { is_expected.to run.with_params(-33.1).and_return(-34) }
end
-
diff --git a/spec/functions/fqdn_rand_string_spec.rb b/spec/functions/fqdn_rand_string_spec.rb
new file mode 100644
index 0000000..e407084
--- /dev/null
+++ b/spec/functions/fqdn_rand_string_spec.rb
@@ -0,0 +1,65 @@
+require 'spec_helper'
+
+describe 'fqdn_rand_string' do
+ let(:default_charset) { %r{\A[a-zA-Z0-9]{100}\z} }
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(ArgumentError, /wrong number of arguments/i) }
+ it { is_expected.to run.with_params(0).and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+ it { is_expected.to run.with_params(1.5).and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+ it { is_expected.to run.with_params(-10).and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+ it { is_expected.to run.with_params("-10").and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+ it { is_expected.to run.with_params("string").and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+ it { is_expected.to run.with_params([]).and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+ it { is_expected.to run.with_params({}).and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+ it { is_expected.to run.with_params(1, 1).and_raise_error(ArgumentError, /second argument must be undef or a string/) }
+ it { is_expected.to run.with_params(1, []).and_raise_error(ArgumentError, /second argument must be undef or a string/) }
+ it { is_expected.to run.with_params(1, {}).and_raise_error(ArgumentError, /second argument must be undef or a string/) }
+ it { is_expected.to run.with_params(100).and_return(default_charset) }
+ it { is_expected.to run.with_params("100").and_return(default_charset) }
+ it { is_expected.to run.with_params(100, nil).and_return(default_charset) }
+ it { is_expected.to run.with_params(100, '').and_return(default_charset) }
+ it { is_expected.to run.with_params(100, 'a').and_return(/\Aa{100}\z/) }
+ it { is_expected.to run.with_params(100, 'ab').and_return(/\A[ab]{100}\z/) }
+
+ it "provides the same 'random' value on subsequent calls for the same host" do
+ expect(fqdn_rand_string(10)).to eql(fqdn_rand_string(10))
+ end
+
+ it "considers the same host and same extra arguments to have the same random sequence" do
+ first_random = fqdn_rand_string(10, :extra_identifier => [1, "same", "host"])
+ second_random = fqdn_rand_string(10, :extra_identifier => [1, "same", "host"])
+
+ expect(first_random).to eql(second_random)
+ end
+
+ it "allows extra arguments to control the random value on a single host" do
+ first_random = fqdn_rand_string(10, :extra_identifier => [1, "different", "host"])
+ second_different_random = fqdn_rand_string(10, :extra_identifier => [2, "different", "host"])
+
+ expect(first_random).not_to eql(second_different_random)
+ end
+
+ it "should return different strings for different hosts" do
+ val1 = fqdn_rand_string(10, :host => "first.host.com")
+ val2 = fqdn_rand_string(10, :host => "second.host.com")
+
+ expect(val1).not_to eql(val2)
+ end
+
+ def fqdn_rand_string(max, args = {})
+ host = args[:host] || '127.0.0.1'
+ charset = args[:charset]
+ extra = args[:extra_identifier] || []
+
+ # workaround not being able to use let(:facts) because some tests need
+ # multiple different hostnames in one context
+ scope.stubs(:lookupvar).with("::fqdn", {}).returns(host)
+
+ function_args = [max]
+ if args.has_key?(:charset) or !extra.empty?
+ function_args << charset
+ end
+ function_args += extra
+ scope.function_fqdn_rand_string(function_args)
+ end
+end
diff --git a/spec/functions/fqdn_rotate_spec.rb b/spec/functions/fqdn_rotate_spec.rb
index 40057d4..db7a717 100755
--- a/spec/functions/fqdn_rotate_spec.rb
+++ b/spec/functions/fqdn_rotate_spec.rb
@@ -1,43 +1,75 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the fqdn_rotate function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'fqdn_rotate' 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(0).and_raise_error(Puppet::ParseError, /Requires either array or string to work with/) }
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work with/) }
+ it { is_expected.to run.with_params('').and_return('') }
+ it { is_expected.to run.with_params('a').and_return('a') }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("fqdn_rotate")).to eq("function_fqdn_rotate")
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(['a']).and_return(['a']) }
+
+ it "should rotate a string and the result should be the same size" do
+ expect(fqdn_rotate("asdf").size).to eq(4)
end
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_fqdn_rotate([]) }.to( raise_error(Puppet::ParseError))
+ it "should rotate a string to give the same results for one host" do
+ val1 = fqdn_rotate("abcdefg", :host => 'one')
+ val2 = fqdn_rotate("abcdefg", :host => 'one')
+ expect(val1).to eq(val2)
end
- it "should rotate a string and the result should be the same size" do
- scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1")
- result = scope.function_fqdn_rotate(["asdf"])
- expect(result.size).to(eq(4))
+ it "allows extra arguments to control the random rotation on a single host" do
+ val1 = fqdn_rotate("abcdefg", :extra_identifier => [1, "different", "host"])
+ val2 = fqdn_rotate("abcdefg", :extra_identifier => [2, "different", "host"])
+ expect(val1).not_to eq(val2)
end
- it "should rotate a string to give the same results for one host" do
- scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1").twice
- expect(scope.function_fqdn_rotate(["abcdefg"])).to eql(scope.function_fqdn_rotate(["abcdefg"]))
+ it "considers the same host and same extra arguments to have the same random rotation" do
+ val1 = fqdn_rotate("abcdefg", :extra_identifier => [1, "same", "host"])
+ val2 = fqdn_rotate("abcdefg", :extra_identifier => [1, "same", "host"])
+ expect(val1).to eq(val2)
end
it "should rotate a string to give different values on different hosts" do
- scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1")
- val1 = scope.function_fqdn_rotate(["abcdefghijklmnopqrstuvwxyz01234567890987654321"])
- scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.2")
- val2 = scope.function_fqdn_rotate(["abcdefghijklmnopqrstuvwxyz01234567890987654321"])
- expect(val1).not_to eql(val2)
+ val1 = fqdn_rotate("abcdefg", :host => 'one')
+ val2 = fqdn_rotate("abcdefg", :host => 'two')
+ expect(val1).not_to eq(val2)
end
it "should accept objects which extend String" do
- class AlsoString < String
+ result = fqdn_rotate(AlsoString.new('asdf'))
+ expect(result).to eq('dfas')
+ end
+
+ it "should use the Puppet::Util.deterministic_rand function" do
+ if Puppet::Util.respond_to?(:deterministic_rand)
+ Puppet::Util.expects(:deterministic_rand).with(44489829212339698569024999901561968770,4)
+ fqdn_rotate("asdf")
+ else
+ skip 'Puppet::Util#deterministic_rand not available'
end
+ end
+
+ it "should not leave the global seed in a deterministic state" do
+ fqdn_rotate("asdf")
+ rand1 = rand()
+ fqdn_rotate("asdf")
+ rand2 = rand()
+ expect(rand1).not_to eql(rand2)
+ end
+
+ def fqdn_rotate(value, args = {})
+ host = args[:host] || '127.0.0.1'
+ extra = args[:extra_identifier] || []
+
+ # workaround not being able to use let(:facts) because some tests need
+ # multiple different hostnames in one context
+ scope.stubs(:lookupvar).with("::fqdn").returns(host)
- scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1")
- value = AlsoString.new("asdf")
- result = scope.function_fqdn_rotate([value])
- result.size.should(eq(4))
+ function_args = [value] + extra
+ scope.function_fqdn_rotate(function_args)
end
end
diff --git a/spec/functions/fqdn_uuid_spec.rb b/spec/functions/fqdn_uuid_spec.rb
new file mode 100644
index 0000000..a2d1618
--- /dev/null
+++ b/spec/functions/fqdn_uuid_spec.rb
@@ -0,0 +1,14 @@
+require 'spec_helper'
+
+describe 'fqdn_uuid' do
+
+ context "Invalid parameters" do
+ it { should run.with_params().and_raise_error(ArgumentError, /No arguments given$/) }
+ end
+
+ context "given string" do
+ it { should run.with_params('puppetlabs.com').and_return('9c70320f-6815-5fc5-ab0f-debe68bf764c') }
+ it { should run.with_params('google.com').and_return('64ee70a4-8cc1-5d25-abf2-dea6c79a09c8') }
+ end
+
+end
diff --git a/spec/functions/get_module_path_spec.rb b/spec/functions/get_module_path_spec.rb
index 38ce645..a39e413 100755
--- a/spec/functions/get_module_path_spec.rb
+++ b/spec/functions/get_module_path_spec.rb
@@ -1,8 +1,12 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:get_module_path) do
- Internals = PuppetlabsSpec::PuppetInternals
+describe 'get_module_path' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/) }
+ it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/) }
+ it { is_expected.to run.with_params('one', 'two', 'three').and_raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/) }
+ it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /Could not find module/) }
+
class StubModule
attr_reader :path
def initialize(path)
@@ -10,37 +14,35 @@ describe Puppet::Parser::Functions.function(:get_module_path) do
end
end
- def scope(environment = "production")
- Internals.scope(:compiler => Internals.compiler(:node => Internals.node(:environment => environment)))
- end
-
- it 'should only allow one argument' do
- expect { scope.function_get_module_path([]) }.to raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/)
- expect { scope.function_get_module_path(['1','2','3']) }.to raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/)
- end
- it 'should raise an exception when the module cannot be found' do
- expect { scope.function_get_module_path(['foo']) }.to raise_error(Puppet::ParseError, /Could not find module/)
- end
describe 'when locating a module' do
let(:modulepath) { "/tmp/does_not_exist" }
let(:path_of_module_foo) { StubModule.new("/tmp/does_not_exist/foo") }
before(:each) { Puppet[:modulepath] = modulepath }
- it 'should be able to find module paths from the modulepath setting' do
- Puppet::Module.expects(:find).with('foo', 'production').returns(path_of_module_foo)
- expect(scope.function_get_module_path(['foo'])).to eq(path_of_module_foo.path)
- end
- it 'should be able to find module paths when the modulepath is a list' do
- Puppet[:modulepath] = modulepath + ":/tmp"
- Puppet::Module.expects(:find).with('foo', 'production').returns(path_of_module_foo)
- expect(scope.function_get_module_path(['foo'])).to eq(path_of_module_foo.path)
+ context 'in the default environment' do
+ before(:each) { Puppet::Module.expects(:find).with('foo', 'rp_env').returns(path_of_module_foo) }
+
+ it { is_expected.to run.with_params('foo').and_return(path_of_module_foo.path) }
+
+ context 'when the modulepath is a list' do
+ before(:each) { Puppet[:modulepath] = modulepath + 'tmp/something_else' }
+
+ it { is_expected.to run.with_params('foo').and_return(path_of_module_foo.path) }
+ end
end
- it 'should respect the environment' do
- skip("Disabled on Puppet 2.6.x") if Puppet.version =~ /^2\.6\b/
- Puppet.settings[:environment] = 'danstestenv'
- Puppet::Module.expects(:find).with('foo', 'danstestenv').returns(path_of_module_foo)
- expect(scope('danstestenv').function_get_module_path(['foo'])).to eq(path_of_module_foo.path)
+
+ context 'in a non-default default environment' do
+ let(:environment) { 'test' }
+ before(:each) { Puppet::Module.expects(:find).with('foo', 'test').returns(path_of_module_foo) }
+
+ it { is_expected.to run.with_params('foo').and_return(path_of_module_foo.path) }
+
+ context 'when the modulepath is a list' do
+ before(:each) { Puppet[:modulepath] = modulepath + 'tmp/something_else' }
+
+ it { is_expected.to run.with_params('foo').and_return(path_of_module_foo.path) }
+ end
end
end
end
diff --git a/spec/functions/getparam_spec.rb b/spec/functions/getparam_spec.rb
index 833c4d4..e4ef9e6 100755
--- a/spec/functions/getparam_spec.rb
+++ b/spec/functions/getparam_spec.rb
@@ -1,76 +1,27 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-require 'rspec-puppet'
-require 'puppet_spec/compiler'
describe 'getparam' do
- include PuppetSpec::Compiler
-
- before :each do
- Puppet::Parser::Functions.autoloader.loadall
- Puppet::Parser::Functions.function(:getparam)
- end
-
- let :node do Puppet::Node.new('localhost') end
- let :compiler do Puppet::Parser::Compiler.new(node) end
- if Puppet.version.to_f >= 3.0
- let :scope do Puppet::Parser::Scope.new(compiler) end
- else
- let :scope do
- newscope = Puppet::Parser::Scope.new
- newscope.compiler = compiler
- newscope.source = Puppet::Resource::Type.new(:node, :localhost)
- newscope
- end
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(ArgumentError, /Must specify a reference/) }
+ it { is_expected.to run.with_params('User[one]').and_raise_error(ArgumentError, /Must specify name of a parameter/) }
+ it { is_expected.to run.with_params('User[one]', 2).and_raise_error(ArgumentError, /Must specify name of a parameter/) }
+ it { is_expected.to run.with_params('User[one]', []).and_raise_error(ArgumentError, /Must specify name of a parameter/) }
+ it { is_expected.to run.with_params('User[one]', {}).and_raise_error(ArgumentError, /Must specify name of a parameter/) }
+
+ describe 'when compared against a user resource with no params' do
+ let(:pre_condition) { 'user { "one": }' }
+
+ it { is_expected.to run.with_params('User[one]', 'ensure').and_return('') }
+ it { is_expected.to run.with_params('User[two]', 'ensure').and_return('') }
+ it { is_expected.to run.with_params('User[one]', 'shell').and_return('') }
end
- it "should exist" do
- expect(Puppet::Parser::Functions.function("getparam")).to eq("function_getparam")
- end
-
- describe 'when a resource is not specified' do
- it { expect { scope.function_getparam([]) }.to raise_error }
- it { expect { scope.function_getparam(['User[dan]']) }.to raise_error }
- it { expect { scope.function_getparam(['User[dan]']) }.to raise_error }
- it { expect { scope.function_getparam(['User[dan]', {}]) }.to raise_error }
- # This seems to be OK because we just check for a string.
- it { expect { scope.function_getparam(['User[dan]', '']) }.to_not raise_error }
- end
-
- describe 'when compared against a resource with no params' do
- let :catalog do
- compile_to_catalog(<<-EOS
- user { "dan": }
- EOS
- )
- end
-
- it do
- expect(scope.function_getparam(['User[dan]', 'shell'])).to eq('')
- end
- end
-
- describe 'when compared against a resource with params' do
- let :catalog do
- compile_to_catalog(<<-EOS
- user { 'dan': ensure => present, shell => '/bin/sh', managehome => false}
- $test = getparam(User[dan], 'shell')
- EOS
- )
- end
-
- it do
- resource = Puppet::Parser::Resource.new(:user, 'dan', {:scope => scope})
- resource.set_parameter('ensure', 'present')
- resource.set_parameter('shell', '/bin/sh')
- resource.set_parameter('managehome', false)
- compiler.add_resource(scope, resource)
+ describe 'when compared against a user resource with params' do
+ let(:pre_condition) { 'user { "one": ensure => present, shell => "/bin/sh", managehome => false, }' }
- expect(scope.function_getparam(['User[dan]', 'shell'])).to eq('/bin/sh')
- expect(scope.function_getparam(['User[dan]', ''])).to eq('')
- expect(scope.function_getparam(['User[dan]', 'ensure'])).to eq('present')
- # TODO: Expected this to be false, figure out why we're getting '' back.
- expect(scope.function_getparam(['User[dan]', 'managehome'])).to eq('')
- end
+ it { is_expected.to run.with_params('User[one]', 'ensure').and_return('present') }
+ it { is_expected.to run.with_params('User[two]', 'ensure').and_return('') }
+ it { is_expected.to run.with_params('User[one]', 'shell').and_return('/bin/sh') }
+ it { is_expected.to run.with_params('User[one]', 'managehome').and_return(false) }
end
end
diff --git a/spec/functions/getvar_spec.rb b/spec/functions/getvar_spec.rb
index 87ab9b5..54f1842 100755
--- a/spec/functions/getvar_spec.rb
+++ b/spec/functions/getvar_spec.rb
@@ -1,37 +1,23 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:getvar) do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
- describe 'when calling getvar from puppet' do
+describe 'getvar' 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 { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
- it "should not compile when no arguments are passed" do
- skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./
- Puppet[:code] = '$foo = getvar()'
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /wrong number of arguments/)
- end
+ it { is_expected.to run.with_params('$::foo').and_return(nil) }
- it "should not compile when too many arguments are passed" do
- skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./
- Puppet[:code] = '$foo = getvar("foo::bar", "baz")'
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /wrong number of arguments/)
- end
-
- it "should lookup variables in other namespaces" do
- skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./
- Puppet[:code] = <<-'ENDofPUPPETcode'
- class site::data { $foo = 'baz' }
- include site::data
- $foo = getvar("site::data::foo")
- if $foo != 'baz' {
- fail('getvar did not return what we expect')
- }
+ context 'given variables in namespaces' do
+ let(:pre_condition) {
+ <<-'ENDofPUPPETcode'
+ class site::data { $foo = 'baz' }
+ include site::data
ENDofPUPPETcode
- scope.compiler.compile
- end
+ }
+
+ it { is_expected.to run.with_params('site::data::foo').and_return('baz') }
+ it { is_expected.to run.with_params('::site::data::foo').and_return('baz') }
+ it { is_expected.to run.with_params('::site::data::bar').and_return(nil) }
end
end
diff --git a/spec/functions/grep_spec.rb b/spec/functions/grep_spec.rb
index 9c671dd..6e0bd6e 100755
--- a/spec/functions/grep_spec.rb
+++ b/spec/functions/grep_spec.rb
@@ -1,19 +1,19 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the grep function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("grep")).to eq("function_grep")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_grep([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should grep contents from an array" do
- result = scope.function_grep([["aaabbb","bbbccc","dddeee"], "bbb"])
- expect(result).to(eq(["aaabbb","bbbccc"]))
- end
+describe 'grep' 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 {
+ pending("grep does not actually check this, and raises NoMethodError instead")
+ is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError, /first argument not an array/)
+ }
+ it {
+ pending("grep does not actually check this, and raises NoMethodError instead")
+ is_expected.to run.with_params(1, 'two').and_raise_error(Puppet::ParseError, /first argument not an array/)
+ }
+ 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([], 'two').and_return([]) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], 'two').and_return(['two']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], 't(wo|hree)').and_return(['two', 'three']) }
end
diff --git a/spec/functions/has_interface_with_spec.rb b/spec/functions/has_interface_with_spec.rb
index 23e09a9..7334d38 100755
--- a/spec/functions/has_interface_with_spec.rb
+++ b/spec/functions/has_interface_with_spec.rb
@@ -1,64 +1,38 @@
-#!/usr/bin/env ruby -S rspec
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:has_interface_with) do
-
- let(:scope) do
- PuppetlabsSpec::PuppetInternals.scope
- end
-
- # The subject of these examples is the method itself.
- subject do
- function_name = Puppet::Parser::Functions.function(:has_interface_with)
- scope.method(function_name)
- end
+describe 'has_interface_with' 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", "three").and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
# We need to mock out the Facts so we can specify how we expect this function
# to behave on different platforms.
context "On Mac OS X Systems" do
- before :each do
- scope.stubs(:lookupvar).with("interfaces").returns('lo0,gif0,stf0,en1,p2p0,fw0,en0,vmnet1,vmnet8,utun0')
- end
- it 'should have loopback (lo0)' do
- expect(subject.call(['lo0'])).to be_truthy
- end
- it 'should not have loopback (lo)' do
- expect(subject.call(['lo'])).to be_falsey
- end
+ let(:facts) { { :interfaces => 'lo0,gif0,stf0,en1,p2p0,fw0,en0,vmnet1,vmnet8,utun0' } }
+ it { is_expected.to run.with_params('lo0').and_return(true) }
+ it { is_expected.to run.with_params('lo').and_return(false) }
end
+
context "On Linux Systems" do
- before :each do
- scope.stubs(:lookupvar).with("interfaces").returns('eth0,lo')
- scope.stubs(:lookupvar).with("ipaddress").returns('10.0.0.1')
- scope.stubs(:lookupvar).with("ipaddress_lo").returns('127.0.0.1')
- scope.stubs(:lookupvar).with("ipaddress_eth0").returns('10.0.0.1')
- scope.stubs(:lookupvar).with('muppet').returns('kermit')
- scope.stubs(:lookupvar).with('muppet_lo').returns('mspiggy')
- scope.stubs(:lookupvar).with('muppet_eth0').returns('kermit')
- end
- it 'should have loopback (lo)' do
- expect(subject.call(['lo'])).to be_truthy
- end
- it 'should not have loopback (lo0)' do
- expect(subject.call(['lo0'])).to be_falsey
- end
- it 'should have ipaddress with 127.0.0.1' do
- expect(subject.call(['ipaddress', '127.0.0.1'])).to be_truthy
- end
- it 'should have ipaddress with 10.0.0.1' do
- expect(subject.call(['ipaddress', '10.0.0.1'])).to be_truthy
- end
- it 'should not have ipaddress with 10.0.0.2' do
- expect(subject.call(['ipaddress', '10.0.0.2'])).to be_falsey
- end
- it 'should have muppet named kermit' do
- expect(subject.call(['muppet', 'kermit'])).to be_truthy
- end
- it 'should have muppet named mspiggy' do
- expect(subject.call(['muppet', 'mspiggy'])).to be_truthy
- end
- it 'should not have muppet named bigbird' do
- expect(subject.call(['muppet', 'bigbird'])).to be_falsey
+ let(:facts) do
+ {
+ :interfaces => 'eth0,lo',
+ :ipaddress => '10.0.0.1',
+ :ipaddress_lo => '127.0.0.1',
+ :ipaddress_eth0 => '10.0.0.1',
+ :muppet => 'kermit',
+ :muppet_lo => 'mspiggy',
+ :muppet_eth0 => 'kermit',
+ }
end
+
+ it { is_expected.to run.with_params('lo').and_return(true) }
+ it { is_expected.to run.with_params('lo0').and_return(false) }
+ it { is_expected.to run.with_params('ipaddress', '127.0.0.1').and_return(true) }
+ it { is_expected.to run.with_params('ipaddress', '10.0.0.1').and_return(true) }
+ it { is_expected.to run.with_params('ipaddress', '8.8.8.8').and_return(false) }
+ it { is_expected.to run.with_params('muppet', 'kermit').and_return(true) }
+ it { is_expected.to run.with_params('muppet', 'mspiggy').and_return(true) }
+ it { is_expected.to run.with_params('muppet', 'bigbird').and_return(false) }
end
end
diff --git a/spec/functions/has_ip_address_spec.rb b/spec/functions/has_ip_address_spec.rb
index 0df12a7..42a5a79 100755
--- a/spec/functions/has_ip_address_spec.rb
+++ b/spec/functions/has_ip_address_spec.rb
@@ -1,39 +1,22 @@
-#!/usr/bin/env ruby -S rspec
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:has_ip_address) do
-
- let(:scope) do
- PuppetlabsSpec::PuppetInternals.scope
- end
-
- subject do
- function_name = Puppet::Parser::Functions.function(:has_ip_address)
- scope.method(function_name)
- end
+describe 'has_ip_address' 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) }
context "On Linux Systems" do
- before :each do
- scope.stubs(:lookupvar).with('interfaces').returns('eth0,lo')
- scope.stubs(:lookupvar).with('ipaddress').returns('10.0.2.15')
- scope.stubs(:lookupvar).with('ipaddress_eth0').returns('10.0.2.15')
- scope.stubs(:lookupvar).with('ipaddress_lo').returns('127.0.0.1')
- end
-
- it 'should have primary address (10.0.2.15)' do
- expect(subject.call(['10.0.2.15'])).to be_truthy
+ let(:facts) do
+ {
+ :interfaces => 'eth0,lo',
+ :ipaddress => '10.0.0.1',
+ :ipaddress_lo => '127.0.0.1',
+ :ipaddress_eth0 => '10.0.0.1',
+ }
end
- it 'should have lookupback address (127.0.0.1)' do
- expect(subject.call(['127.0.0.1'])).to be_truthy
- end
-
- it 'should not have other address' do
- expect(subject.call(['192.1681.1.1'])).to be_falsey
- end
-
- it 'should not have "mspiggy" on an interface' do
- expect(subject.call(['mspiggy'])).to be_falsey
- end
+ it { is_expected.to run.with_params('127.0.0.1').and_return(true) }
+ it { is_expected.to run.with_params('10.0.0.1').and_return(true) }
+ it { is_expected.to run.with_params('8.8.8.8').and_return(false) }
end
end
diff --git a/spec/functions/has_ip_network_spec.rb b/spec/functions/has_ip_network_spec.rb
index 2a2578e..7b5fe66 100755
--- a/spec/functions/has_ip_network_spec.rb
+++ b/spec/functions/has_ip_network_spec.rb
@@ -1,36 +1,22 @@
-#!/usr/bin/env ruby -S rspec
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:has_ip_network) do
-
- let(:scope) do
- PuppetlabsSpec::PuppetInternals.scope
- end
-
- subject do
- function_name = Puppet::Parser::Functions.function(:has_ip_network)
- scope.method(function_name)
- end
+describe 'has_ip_network' 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) }
context "On Linux Systems" do
- before :each do
- scope.stubs(:lookupvar).with('interfaces').returns('eth0,lo')
- scope.stubs(:lookupvar).with('network').returns(:undefined)
- scope.stubs(:lookupvar).with('network_eth0').returns('10.0.2.0')
- scope.stubs(:lookupvar).with('network_lo').returns('127.0.0.1')
- end
-
- it 'should have primary network (10.0.2.0)' do
- expect(subject.call(['10.0.2.0'])).to be_truthy
- end
-
- it 'should have loopback network (127.0.0.0)' do
- expect(subject.call(['127.0.0.1'])).to be_truthy
+ let(:facts) do
+ {
+ :interfaces => 'eth0,lo',
+ :network => :undefined,
+ :network_lo => '127.0.0.0',
+ :network_eth0 => '10.0.0.0',
+ }
end
- it 'should not have other network' do
- expect(subject.call(['192.168.1.0'])).to be_falsey
- end
+ it { is_expected.to run.with_params('127.0.0.0').and_return(true) }
+ it { is_expected.to run.with_params('10.0.0.0').and_return(true) }
+ it { is_expected.to run.with_params('8.8.8.0').and_return(false) }
end
end
-
diff --git a/spec/functions/has_key_spec.rb b/spec/functions/has_key_spec.rb
index 6b71800..965d5a6 100755
--- a/spec/functions/has_key_spec.rb
+++ b/spec/functions/has_key_spec.rb
@@ -1,42 +1,15 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:has_key) do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- describe 'when calling has_key from puppet' do
- it "should not compile when no arguments are passed" do
- skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./
- Puppet[:code] = '$x = has_key()'
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /wrong number of arguments/)
- end
-
- it "should not compile when 1 argument is passed" do
- skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./
- Puppet[:code] = "$x = has_key('foo')"
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /wrong number of arguments/)
- end
-
- it "should require the first value to be a Hash" do
- skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./
- Puppet[:code] = "$x = has_key('foo', 'bar')"
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /expects the first argument to be a hash/)
- end
- end
-
- describe 'when calling the function has_key from a scope instance' do
- it 'should detect existing keys' do
- expect(scope.function_has_key([{'one' => 1}, 'one'])).to be_truthy
- end
-
- it 'should detect existing keys' do
- expect(scope.function_has_key([{'one' => 1}, 'two'])).to be_falsey
- end
- end
+describe 'has_key' 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", "two").and_raise_error(Puppet::ParseError, /expects the first argument to be a hash/) }
+ it { is_expected.to run.with_params(1, "two").and_raise_error(Puppet::ParseError, /expects the first argument to be a hash/) }
+ it { is_expected.to run.with_params([], "two").and_raise_error(Puppet::ParseError, /expects the first argument to be a hash/) }
+
+ it { is_expected.to run.with_params({ 'key' => 'value' }, "key").and_return(true) }
+ it { is_expected.to run.with_params({}, "key").and_return(false) }
+ it { is_expected.to run.with_params({ 'key' => 'value'}, "not a key").and_return(false) }
end
diff --git a/spec/functions/hash_spec.rb b/spec/functions/hash_spec.rb
index ec2988b..4fe99ce 100755
--- a/spec/functions/hash_spec.rb
+++ b/spec/functions/hash_spec.rb
@@ -1,19 +1,14 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the hash function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("hash")).to eq("function_hash")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_hash([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should convert an array to a hash" do
- result = scope.function_hash([['a',1,'b',2,'c',3]])
- expect(result).to(eq({'a'=>1,'b'=>2,'c'=>3}))
- end
+describe 'hash' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params([], 'two').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params(['one']).and_raise_error(Puppet::ParseError, /Unable to compute/) }
+ it { is_expected.to run.with_params([]).and_return({}) }
+ it { is_expected.to run.with_params(['key1', 'value1']).and_return({ 'key1' => 'value1' }) }
+ it { is_expected.to run.with_params(['key1', 'value1', 'key2', 'value2']).and_return({ 'key1' => 'value1', 'key2' => 'value2' }) }
end
diff --git a/spec/functions/intersection_spec.rb b/spec/functions/intersection_spec.rb
index 6361304..c0f6086 100755
--- a/spec/functions/intersection_spec.rb
+++ b/spec/functions/intersection_spec.rb
@@ -1,19 +1,21 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the intersection function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("intersection")).to eq("function_intersection")
- end
-
- it "should raise a ParseError if there are fewer than 2 arguments" do
- expect { scope.function_intersection([]) }.to( raise_error(Puppet::ParseError) )
- end
-
- it "should return the intersection of two arrays" do
- result = scope.function_intersection([["a","b","c"],["b","c","d"]])
- expect(result).to(eq(["b","c"]))
- end
+describe 'intersection' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one', 'two', 'three').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params('one', []).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([], 'two').and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params({}, {}).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([], []).and_return([]) }
+ it { is_expected.to run.with_params([], ['one']).and_return([]) }
+ it { is_expected.to run.with_params(['one'], []).and_return([]) }
+ it { is_expected.to run.with_params(['one'], ['one']).and_return(['one']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'three']).and_return(['two', 'three']) }
+ it { is_expected.to run.with_params(['one', 'two', 'two', 'three'], ['two', 'three']).and_return(['two', 'three']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'two', 'three']).and_return(['two', 'three']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'three', 'four']).and_return(['two', 'three']) }
+ it 'should not confuse types' do is_expected.to run.with_params(['1', '2', '3'], [1, 2]).and_return([]) end
end
diff --git a/spec/functions/is_a_spec.rb b/spec/functions/is_a_spec.rb
new file mode 100644
index 0000000..8dec13f
--- /dev/null
+++ b/spec/functions/is_a_spec.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+if ENV["FUTURE_PARSER"] == 'yes'
+ describe 'type_of' do
+ pending 'teach rspec-puppet to load future-only functions under 3.7.5' do
+ it { is_expected.not_to eq(nil) }
+ end
+ end
+end
+
+if Puppet.version.to_f >= 4.0
+ describe 'is_a' 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('', '').and_raise_error(ArgumentError) }
+
+ it 'succeeds when comparing a string and a string' do
+ is_expected.to run.with_params('hello world', String).and_return(true)
+ end
+
+ it 'fails when comparing an integer and a string' do
+ is_expected.to run.with_params(5, String).and_return(false)
+ end
+ end
+end
diff --git a/spec/functions/is_array_spec.rb b/spec/functions/is_array_spec.rb
index 94920a4..e89f54b 100755
--- a/spec/functions/is_array_spec.rb
+++ b/spec/functions/is_array_spec.rb
@@ -1,29 +1,36 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the is_array function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("is_array")).to eq("function_is_array")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_is_array([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return true if passed an array" do
- result = scope.function_is_array([[1,2,3]])
- expect(result).to(eq(true))
- end
-
- it "should return false if passed a hash" do
- result = scope.function_is_array([{'a'=>1}])
- expect(result).to(eq(false))
- end
-
- it "should return false if passed a string" do
- result = scope.function_is_array(["asdf"])
- expect(result).to(eq(false))
+describe 'is_array' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params([], []).and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params([]).and_return(true) }
+ it { is_expected.to run.with_params(['one']).and_return(true) }
+ it { is_expected.to run.with_params([1]).and_return(true) }
+ it { is_expected.to run.with_params([{}]).and_return(true) }
+ it { is_expected.to run.with_params([[]]).and_return(true) }
+ it { is_expected.to run.with_params('').and_return(false) }
+ it { is_expected.to run.with_params('one').and_return(false) }
+ it { is_expected.to run.with_params(1).and_return(false) }
+ it { is_expected.to run.with_params({}).and_return(false) }
+ context 'Checking for deprecation warning' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
+ # Checking for deprecation warning, which should only be provoked when the env variable for it is set.
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params(['1.2.3.4']).and_return(true)
+ end
+ it 'should display no warning for deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "false"
+ scope.expects(:warning).with(includes('This method is deprecated')).never
+ is_expected.to run.with_params(['1.2.3.4']).and_return(true)
+ end
end
end
diff --git a/spec/functions/is_bool_spec.rb b/spec/functions/is_bool_spec.rb
index 4a342ba..d21345c 100755
--- a/spec/functions/is_bool_spec.rb
+++ b/spec/functions/is_bool_spec.rb
@@ -1,44 +1,33 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the is_bool function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("is_bool")).to eq("function_is_bool")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_is_bool([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return true if passed a TrueClass" do
- result = scope.function_is_bool([true])
- expect(result).to(eq(true))
- end
-
- it "should return true if passed a FalseClass" do
- result = scope.function_is_bool([false])
- expect(result).to(eq(true))
- end
-
- it "should return false if passed the string 'true'" do
- result = scope.function_is_bool(['true'])
- expect(result).to(eq(false))
- end
-
- it "should return false if passed the string 'false'" do
- result = scope.function_is_bool(['false'])
- expect(result).to(eq(false))
- end
-
- it "should return false if passed an array" do
- result = scope.function_is_bool([["a","b"]])
- expect(result).to(eq(false))
- end
-
- it "should return false if passed a hash" do
- result = scope.function_is_bool([{"a" => "b"}])
- expect(result).to(eq(false))
- end
+describe 'is_bool' 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(true, false).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ it { is_expected.to run.with_params(true).and_return(true) }
+ it { is_expected.to run.with_params(false).and_return(true) }
+ it { is_expected.to run.with_params([1]).and_return(false) }
+ it { is_expected.to run.with_params([{}]).and_return(false) }
+ it { is_expected.to run.with_params([[]]).and_return(false) }
+ it { is_expected.to run.with_params([true]).and_return(false) }
+ it { is_expected.to run.with_params('true').and_return(false) }
+ it { is_expected.to run.with_params('false').and_return(false) }
+ context 'Checking for deprecation warning' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
+ # Checking for deprecation warning, which should only be provoked when the env variable for it is set.
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params(true).and_return(true)
+ end
+ it 'should display no warning for deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "false"
+ scope.expects(:warning).with(includes('This method is deprecated')).never
+ is_expected.to run.with_params(false).and_return(true)
+ end
+ end
end
+
diff --git a/spec/functions/is_domain_name_spec.rb b/spec/functions/is_domain_name_spec.rb
index 4d05f5c..c1bf0e3 100755
--- a/spec/functions/is_domain_name_spec.rb
+++ b/spec/functions/is_domain_name_spec.rb
@@ -1,64 +1,43 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the is_domain_name function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("is_domain_name")).to eq("function_is_domain_name")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_is_domain_name([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return true if a valid short domain name" do
- result = scope.function_is_domain_name(["x.com"])
- expect(result).to(be_truthy)
- end
-
- it "should return true if the domain is ." do
- result = scope.function_is_domain_name(["."])
- expect(result).to(be_truthy)
- end
-
- it "should return true if the domain is x.com." do
- result = scope.function_is_domain_name(["x.com."])
- expect(result).to(be_truthy)
- end
-
- it "should return true if a valid domain name" do
- result = scope.function_is_domain_name(["foo.bar.com"])
- expect(result).to(be_truthy)
- end
-
- it "should allow domain parts to start with numbers" do
- result = scope.function_is_domain_name(["3foo.2bar.com"])
- expect(result).to(be_truthy)
- end
-
- it "should allow domain to end with a dot" do
- result = scope.function_is_domain_name(["3foo.2bar.com."])
- expect(result).to(be_truthy)
- end
-
- it "should allow a single part domain" do
- result = scope.function_is_domain_name(["orange"])
- expect(result).to(be_truthy)
- end
-
- it "should return false if domain parts start with hyphens" do
- result = scope.function_is_domain_name(["-3foo.2bar.com"])
- expect(result).to(be_falsey)
- end
-
- it "should return true if domain contains hyphens" do
- result = scope.function_is_domain_name(["3foo-bar.2bar-fuzz.com"])
- expect(result).to(be_truthy)
- end
-
- it "should return false if domain name contains spaces" do
- result = scope.function_is_domain_name(["not valid"])
- expect(result).to(be_falsey)
+describe 'is_domain_name' 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 { is_expected.to run.with_params(1).and_return(false) }
+ it { is_expected.to run.with_params([]).and_return(false) }
+ it { is_expected.to run.with_params({}).and_return(false) }
+ it { is_expected.to run.with_params('').and_return(false) }
+ it { is_expected.to run.with_params('.').and_return(true) }
+ it { is_expected.to run.with_params('com').and_return(true) }
+ it { is_expected.to run.with_params('com.').and_return(true) }
+ it { is_expected.to run.with_params('x.com').and_return(true) }
+ it { is_expected.to run.with_params('x.com.').and_return(true) }
+ it { is_expected.to run.with_params('foo.example.com').and_return(true) }
+ it { is_expected.to run.with_params('foo.example.com.').and_return(true) }
+ it { is_expected.to run.with_params('2foo.example.com').and_return(true) }
+ it { is_expected.to run.with_params('2foo.example.com.').and_return(true) }
+ it { is_expected.to run.with_params('www.2foo.example.com').and_return(true) }
+ it { is_expected.to run.with_params('www.2foo.example.com.').and_return(true) }
+ describe 'inputs with spaces' do
+ it { is_expected.to run.with_params('invalid domain').and_return(false) }
+ end
+ describe 'inputs with hyphens' do
+ it { is_expected.to run.with_params('foo-bar.example.com').and_return(true) }
+ it { is_expected.to run.with_params('foo-bar.example.com.').and_return(true) }
+ it { is_expected.to run.with_params('www.foo-bar.example.com').and_return(true) }
+ it { is_expected.to run.with_params('www.foo-bar.example.com.').and_return(true) }
+ it { is_expected.to run.with_params('-foo.example.com').and_return(false) }
+ it { is_expected.to run.with_params('-foo.example.com').and_return(false) }
+ end
+ # Values obtained from Facter values will be frozen strings
+ # in newer versions of Facter:
+ it { is_expected.to run.with_params('www.example.com'.freeze).and_return(true) }
+ describe 'top level domain must be alphabetic if there are multiple labels' do
+ it { is_expected.to run.with_params('2com').and_return(true) }
+ it { is_expected.to run.with_params('www.example.2com').and_return(false) }
+ end
+ describe 'IP addresses are not domain names' do
+ it { is_expected.to run.with_params('192.168.1.1').and_return(false) }
end
end
diff --git a/spec/functions/is_email_address_spec.rb b/spec/functions/is_email_address_spec.rb
new file mode 100755
index 0000000..8b7b358
--- /dev/null
+++ b/spec/functions/is_email_address_spec.rb
@@ -0,0 +1,14 @@
+require 'spec_helper'
+
+describe 'is_email_address' 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('bob@gmail.com').and_return(true) }
+ it { is_expected.to run.with_params('alice+puppetlabs.com@gmail.com').and_return(true) }
+ it { is_expected.to run.with_params('peter.parker@gmail.com').and_return(true) }
+ it { is_expected.to run.with_params('1.2.3@domain').and_return(false) }
+ it { is_expected.to run.with_params('1.2.3.4.5@').and_return(false) }
+ it { is_expected.to run.with_params({}).and_return(false) }
+ it { is_expected.to run.with_params([]).and_return(false) }
+end
diff --git a/spec/functions/is_float_spec.rb b/spec/functions/is_float_spec.rb
index d926634..af3322e 100755
--- a/spec/functions/is_float_spec.rb
+++ b/spec/functions/is_float_spec.rb
@@ -1,33 +1,42 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the is_float function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'is_float' do
- it "should exist" do
- expect(Puppet::Parser::Functions.function("is_float")).to eq("function_is_float")
- end
+ it { is_expected.not_to eq(nil) }
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_is_float([]) }.to( raise_error(Puppet::ParseError))
- end
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ it { is_expected.to run.with_params(0.1, 0.2).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
- it "should return true if a float" do
- result = scope.function_is_float(["0.12"])
- expect(result).to(eq(true))
+ describe 'passing a string' do
+ it { is_expected.to run.with_params('0.1').and_return(true) }
+ it { is_expected.to run.with_params('1.0').and_return(true) }
+ it { is_expected.to run.with_params('1').and_return(false) }
+ it { is_expected.to run.with_params('one').and_return(false) }
+ it { is_expected.to run.with_params('one 1.0').and_return(false) }
+ it { is_expected.to run.with_params('1.0 one').and_return(false) }
end
- it "should return false if a string" do
- result = scope.function_is_float(["asdf"])
- expect(result).to(eq(false))
+ describe 'passing numbers' do
+ it { is_expected.to run.with_params(0.1).and_return(true) }
+ it { is_expected.to run.with_params(1.0).and_return(true) }
+ it { is_expected.to run.with_params(1).and_return(false) }
end
- it "should return false if an integer" do
- result = scope.function_is_float(["3"])
- expect(result).to(eq(false))
- end
- it "should return true if a float is created from an arithmetical operation" do
- result = scope.function_is_float([3.2*2])
- expect(result).to(eq(true))
+ context 'Checking for deprecation warning' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
+ # Checking for deprecation warning, which should only be provoked when the env variable for it is set.
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params(2.2).and_return(true)
+ end
+ it 'should display no warning for deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "false"
+ scope.expects(:warning).with(includes('This method is deprecated')).never
+ is_expected.to run.with_params(1.0).and_return(true)
+ end
end
+
end
diff --git a/spec/functions/is_function_available.rb b/spec/functions/is_function_available.rb
index 3a9aa1b..44f08c0 100755
--- a/spec/functions/is_function_available.rb
+++ b/spec/functions/is_function_available.rb
@@ -1,31 +1,9 @@
-#!/usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the is_function_available function" do
- before :all do
- Puppet::Parser::Functions.autoloader.loadall
- end
-
- before :each do
- @scope = Puppet::Parser::Scope.new
- end
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("is_function_available")).to eq("function_is_function_available")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { @scope.function_is_function_available([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return false if a nonexistent function is passed" do
- result = @scope.function_is_function_available(['jeff_mccunes_left_sock'])
- expect(result).to(eq(false))
- end
-
- it "should return true if an available function is passed" do
- result = @scope.function_is_function_available(['require'])
- expect(result).to(eq(true))
- end
-
+describe 'is_function_available' 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 { is_expected.to run.with_params('include').and_return(true) }
+ it { is_expected.to run.with_params('no_such_function').and_return(false) }
end
diff --git a/spec/functions/is_hash_spec.rb b/spec/functions/is_hash_spec.rb
index a849411..c2599a0 100755
--- a/spec/functions/is_hash_spec.rb
+++ b/spec/functions/is_hash_spec.rb
@@ -1,29 +1,11 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the is_hash function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("is_hash")).to eq("function_is_hash")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_is_hash([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return true if passed a hash" do
- result = scope.function_is_hash([{"a"=>1,"b"=>2}])
- expect(result).to(eq(true))
- end
-
- it "should return false if passed an array" do
- result = scope.function_is_hash([["a","b"]])
- expect(result).to(eq(false))
- end
-
- it "should return false if passed a string" do
- result = scope.function_is_hash(["asdf"])
- expect(result).to(eq(false))
- end
+describe 'is_hash' 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('').and_return(false) }
+ it { is_expected.to run.with_params({}).and_return(true) }
+ it { is_expected.to run.with_params([]).and_return(false) }
+ it { is_expected.to run.with_params(1).and_return(false) }
end
diff --git a/spec/functions/is_integer_spec.rb b/spec/functions/is_integer_spec.rb
index f0cbca8..b296830 100755
--- a/spec/functions/is_integer_spec.rb
+++ b/spec/functions/is_integer_spec.rb
@@ -1,69 +1,45 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the is_integer function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'is_integer' 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(1, 2).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+ it { is_expected.to run.with_params(3).and_return(true) }
+ it { is_expected.to run.with_params('3').and_return(true) }
+ it { is_expected.to run.with_params(-3).and_return(true) }
+ it { is_expected.to run.with_params('-3').and_return(true) }
+
+ it { is_expected.to run.with_params(3.7).and_return(false) }
+ it { is_expected.to run.with_params('3.7').and_return(false) }
+ it { is_expected.to run.with_params(-3.7).and_return(false) }
+ it { is_expected.to run.with_params('3.7').and_return(false) }
+
+ it { is_expected.to run.with_params('one').and_return(false) }
+ it { is_expected.to run.with_params([]).and_return(false) }
+ it { is_expected.to run.with_params([1]).and_return(false) }
+ it { is_expected.to run.with_params({}).and_return(false) }
+ it { is_expected.to run.with_params(true).and_return(false) }
+ it { is_expected.to run.with_params(false).and_return(false) }
+ it { is_expected.to run.with_params('0001234').and_return(false) }
+
+ context 'Checking for deprecation warning' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
+ # Checking for deprecation warning, which should only be provoked when the env variable for it is set.
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params(50).and_return(true)
+ end
+ it 'should display no warning for deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "false"
+ scope.expects(:warning).with(includes('This method is deprecated')).never
+ is_expected.to run.with_params(50).and_return(true)
+ end
+ end
- it "should exist" do
- expect(Puppet::Parser::Functions.function("is_integer")).to eq("function_is_integer")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_is_integer([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return true if an integer" do
- result = scope.function_is_integer(["3"])
- expect(result).to(eq(true))
- end
-
- it "should return true if a negative integer" do
- result = scope.function_is_integer(["-7"])
- expect(result).to(eq(true))
- end
-
- it "should return false if a float" do
- result = scope.function_is_integer(["3.2"])
- expect(result).to(eq(false))
- end
-
- it "should return false if a string" do
- result = scope.function_is_integer(["asdf"])
- expect(result).to(eq(false))
- end
-
- it "should return true if an integer is created from an arithmetical operation" do
- result = scope.function_is_integer([3*2])
- expect(result).to(eq(true))
- end
-
- it "should return false if an array" do
- result = scope.function_is_numeric([["asdf"]])
- expect(result).to(eq(false))
- end
-
- it "should return false if a hash" do
- result = scope.function_is_numeric([{"asdf" => false}])
- expect(result).to(eq(false))
- end
-
- it "should return false if a boolean" do
- result = scope.function_is_numeric([true])
- expect(result).to(eq(false))
- end
-
- it "should return false if a whitespace is in the string" do
- result = scope.function_is_numeric([" -1324"])
- expect(result).to(eq(false))
- end
-
- it "should return false if it is zero prefixed" do
- result = scope.function_is_numeric(["0001234"])
- expect(result).to(eq(false))
- end
-
- it "should return false if it is wrapped inside an array" do
- result = scope.function_is_numeric([[1234]])
- expect(result).to(eq(false))
- end
end
diff --git a/spec/functions/is_ip_address_spec.rb b/spec/functions/is_ip_address_spec.rb
index c16d12b..39525d7 100755
--- a/spec/functions/is_ip_address_spec.rb
+++ b/spec/functions/is_ip_address_spec.rb
@@ -1,39 +1,40 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the is_ip_address function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("is_ip_address")).to eq("function_is_ip_address")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_is_ip_address([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return true if an IPv4 address" do
- result = scope.function_is_ip_address(["1.2.3.4"])
- expect(result).to(eq(true))
- end
-
- it "should return true if a full IPv6 address" do
- result = scope.function_is_ip_address(["fe80:0000:cd12:d123:e2f8:47ff:fe09:dd74"])
- expect(result).to(eq(true))
- end
-
- it "should return true if a compressed IPv6 address" do
- result = scope.function_is_ip_address(["fe00::1"])
- expect(result).to(eq(true))
- end
-
- it "should return false if not valid" do
- result = scope.function_is_ip_address(["asdf"])
- expect(result).to(eq(false))
- end
-
- it "should return false if IP octets out of range" do
- result = scope.function_is_ip_address(["1.1.1.300"])
- expect(result).to(eq(false))
+describe 'is_ip_address' 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('1.2.3.4').and_return(true) }
+ it { is_expected.to run.with_params('1.2.3.255').and_return(true) }
+ it { is_expected.to run.with_params('1.2.3.256').and_return(false) }
+ it { is_expected.to run.with_params('1.2.3').and_return(false) }
+ it { is_expected.to run.with_params('1.2.3.4.5').and_return(false) }
+ it { is_expected.to run.with_params('fe00::1').and_return(true) }
+ it { is_expected.to run.with_params('fe80:0000:cd12:d123:e2f8:47ff:fe09:dd74').and_return(true) }
+ it { is_expected.to run.with_params('FE80:0000:CD12:D123:E2F8:47FF:FE09:DD74').and_return(true) }
+ it { is_expected.to run.with_params('fe80:0000:cd12:d123:e2f8:47ff:fe09:zzzz').and_return(false) }
+ it { is_expected.to run.with_params('fe80:0000:cd12:d123:e2f8:47ff:fe09').and_return(false) }
+ it { is_expected.to run.with_params('fe80:0000:cd12:d123:e2f8:47ff:fe09:dd74:dd74').and_return(false) }
+ it { is_expected.to run.with_params('').and_return(false) }
+ it { is_expected.to run.with_params('one').and_return(false) }
+ it { is_expected.to run.with_params(1).and_return(false) }
+ it { is_expected.to run.with_params({}).and_return(false) }
+ it { is_expected.to run.with_params([]).and_return(false) }
+
+ context 'Checking for deprecation warning', if: Puppet.version.to_f < 4.0 do
+ # Checking for deprecation warning, which should only be provoked when the env variable for it is set.
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params('1.2.3.4').and_return(true)
+ end
+ it 'should display no warning for deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "false"
+ scope.expects(:warning).with(includes('This method is deprecated')).never
+ is_expected.to run.with_params('1.2.3.4').and_return(true)
+ end
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
end
end
diff --git a/spec/functions/is_ipv4_address_spec.rb b/spec/functions/is_ipv4_address_spec.rb
new file mode 100644
index 0000000..985260c
--- /dev/null
+++ b/spec/functions/is_ipv4_address_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe 'is_ipv4_address' 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) }
+
+ SharedData::IPV4_PATTERNS.each do |value|
+ it { is_expected.to run.with_params(value).and_return(true) }
+ end
+
+ SharedData::IPV4_NEGATIVE_PATTERNS.each do |value|
+ it { is_expected.to run.with_params(value).and_return(false) }
+ end
+
+ context 'Checking for deprecation warning', if: Puppet.version.to_f < 4.0 do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
+ # Checking for deprecation warning, which should only be provoked when the env variable for it is set.
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params(SharedData::IPV4_PATTERNS.first).and_return(true)
+ end
+ it 'should display no warning for deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "false"
+ scope.expects(:warning).with(includes('This method is deprecated')).never
+ is_expected.to run.with_params(SharedData::IPV4_PATTERNS.first).and_return(true)
+ end
+ end
+end
diff --git a/spec/functions/is_ipv6_address_spec.rb b/spec/functions/is_ipv6_address_spec.rb
new file mode 100644
index 0000000..acd6a87
--- /dev/null
+++ b/spec/functions/is_ipv6_address_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe 'is_ipv6_address' 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('2001:0db8:85a3:0000:0000:8a2e:0370:7334').and_return(true) }
+ it { is_expected.to run.with_params('85a3:0000:0000:8a2e:0370:7334:100.100.100.100').and_return(true) }
+ it { is_expected.to run.with_params('1.2.3').and_return(false) }
+ it { is_expected.to run.with_params('1.2.3.4.5').and_return(false) }
+ it { is_expected.to run.with_params('').and_return(false) }
+ it { is_expected.to run.with_params('one').and_return(false) }
+
+ context 'Checking for deprecation warning', if: Puppet.version.to_f < 4.0 do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
+ # Checking for deprecation warning, which should only be provoked when the env variable for it is set.
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params('2001:0db8:85a3:0000:0000:8a2e:0370:7334').and_return(true)
+ end
+ it 'should display no warning for deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "false"
+ scope.expects(:warning).with(includes('This method is deprecated')).never
+ is_expected.to run.with_params('2001:0db8:85a3:0000:0000:8a2e:0370:7334').and_return(true)
+ end
+ end
+end
diff --git a/spec/functions/is_mac_address_spec.rb b/spec/functions/is_mac_address_spec.rb
index 66edd19..5f76a91 100755
--- a/spec/functions/is_mac_address_spec.rb
+++ b/spec/functions/is_mac_address_spec.rb
@@ -1,29 +1,24 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the is_mac_address function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("is_mac_address")).to eq("function_is_mac_address")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_is_mac_address([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return true if a valid mac address" do
- result = scope.function_is_mac_address(["00:a0:1f:12:7f:a0"])
- expect(result).to(eq(true))
- end
-
- it "should return false if octets are out of range" do
- result = scope.function_is_mac_address(["00:a0:1f:12:7f:g0"])
- expect(result).to(eq(false))
- end
-
- it "should return false if not valid" do
- result = scope.function_is_mac_address(["not valid"])
- expect(result).to(eq(false))
- end
+describe 'is_mac_address' 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('00:a0:1f:12:7f:a0').and_return(true) }
+ it { is_expected.to run.with_params('00:A0:1F:12:7F:A0').and_return(true) }
+ it { is_expected.to run.with_params('00:00:00:00:00:0g').and_return(false) }
+ it { is_expected.to run.with_params('').and_return(false) }
+ it { is_expected.to run.with_params('one').and_return(false) }
+ it {
+ pending "should properly typecheck its arguments"
+ is_expected.to run.with_params(1).and_return(false)
+ }
+ it {
+ pending "should properly typecheck its arguments"
+ is_expected.to run.with_params({}).and_return(false)
+ }
+ it {
+ pending "should properly typecheck its arguments"
+ is_expected.to run.with_params([]).and_return(false)
+ }
end
diff --git a/spec/functions/is_numeric_spec.rb b/spec/functions/is_numeric_spec.rb
index 4176961..5962d8a 100755
--- a/spec/functions/is_numeric_spec.rb
+++ b/spec/functions/is_numeric_spec.rb
@@ -1,119 +1,48 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the is_numeric function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("is_numeric")).to eq("function_is_numeric")
- end
-
- it "should raise a ParseError if there is less than 1 argument" do
- expect { scope.function_is_numeric([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return true if an integer" do
- result = scope.function_is_numeric(["3"])
- expect(result).to(eq(true))
- end
-
- it "should return true if a float" do
- result = scope.function_is_numeric(["3.2"])
- expect(result).to(eq(true))
- end
-
- it "should return true if an integer is created from an arithmetical operation" do
- result = scope.function_is_numeric([3*2])
- expect(result).to(eq(true))
- end
-
- it "should return true if a float is created from an arithmetical operation" do
- result = scope.function_is_numeric([3.2*2])
- expect(result).to(eq(true))
- end
-
- it "should return false if a string" do
- result = scope.function_is_numeric(["asdf"])
- expect(result).to(eq(false))
- end
-
- it "should return false if an array" do
- result = scope.function_is_numeric([["asdf"]])
- expect(result).to(eq(false))
- end
-
- it "should return false if an array of integers" do
- result = scope.function_is_numeric([[1,2,3,4]])
- expect(result).to(eq(false))
- end
-
- it "should return false if a hash" do
- result = scope.function_is_numeric([{"asdf" => false}])
- expect(result).to(eq(false))
- end
-
- it "should return false if a hash with numbers in it" do
- result = scope.function_is_numeric([{1 => 2}])
- expect(result).to(eq(false))
- end
-
- it "should return false if a boolean" do
- result = scope.function_is_numeric([true])
- expect(result).to(eq(false))
- end
-
- it "should return true if a negative float with exponent" do
- result = scope.function_is_numeric(["-342.2315e-12"])
- expect(result).to(eq(true))
- end
-
- it "should return false if a negative integer with whitespaces before/after the dash" do
- result = scope.function_is_numeric([" - 751"])
- expect(result).to(eq(false))
+describe 'is_numeric' 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(1, 2).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+ it { is_expected.to run.with_params(3).and_return(true) }
+ it { is_expected.to run.with_params('3').and_return(true) }
+ it { is_expected.to run.with_params(-3).and_return(true) }
+ it { is_expected.to run.with_params('-3').and_return(true) }
+
+ it { is_expected.to run.with_params(3.7).and_return(true) }
+ it { is_expected.to run.with_params('3.7').and_return(true) }
+ it { is_expected.to run.with_params(-3.7).and_return(true) }
+ it { is_expected.to run.with_params('3.7').and_return(true) }
+
+ it { is_expected.to run.with_params('-342.2315e-12').and_return(true) }
+
+ it { is_expected.to run.with_params('one').and_return(false) }
+ it { is_expected.to run.with_params([]).and_return(false) }
+ it { is_expected.to run.with_params([1]).and_return(false) }
+ it { is_expected.to run.with_params({}).and_return(false) }
+ it { is_expected.to run.with_params(true).and_return(false) }
+ it { is_expected.to run.with_params(false).and_return(false) }
+ it { is_expected.to run.with_params('0001234').and_return(false) }
+ it { is_expected.to run.with_params(' - 1234').and_return(false) }
+
+ context 'Checking for deprecation warning' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
+ # Checking for deprecation warning, which should only be provoked when the env variable for it is set.
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params(7).and_return(true)
+ end
+ it 'should display no warning for deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "false"
+ scope.expects(:warning).with(includes('This method is deprecated')).never
+ is_expected.to run.with_params(7).and_return(true)
+ end
end
-# it "should return true if a hexadecimal" do
-# result = scope.function_is_numeric(["0x52F8c"])
-# result.should(eq(true))
-# end
-#
-# it "should return true if a hexadecimal with uppercase 0X prefix" do
-# result = scope.function_is_numeric(["0X52F8c"])
-# result.should(eq(true))
-# end
-#
-# it "should return false if a hexadecimal without a prefix" do
-# result = scope.function_is_numeric(["52F8c"])
-# result.should(eq(false))
-# end
-#
-# it "should return true if a octal" do
-# result = scope.function_is_numeric(["0751"])
-# result.should(eq(true))
-# end
-#
-# it "should return true if a negative hexadecimal" do
-# result = scope.function_is_numeric(["-0x52F8c"])
-# result.should(eq(true))
-# end
-#
-# it "should return true if a negative octal" do
-# result = scope.function_is_numeric(["-0751"])
-# result.should(eq(true))
-# end
-#
-# it "should return false if a negative octal with whitespaces before/after the dash" do
-# result = scope.function_is_numeric([" - 0751"])
-# result.should(eq(false))
-# end
-#
-# it "should return false if a bad hexadecimal" do
-# result = scope.function_is_numeric(["0x23d7g"])
-# result.should(eq(false))
-# end
-#
-# it "should return false if a bad octal" do
-# result = scope.function_is_numeric(["0287"])
-# result.should(eq(false))
-# end
end
diff --git a/spec/functions/is_string_spec.rb b/spec/functions/is_string_spec.rb
index 6a0801a..e92f85c 100755
--- a/spec/functions/is_string_spec.rb
+++ b/spec/functions/is_string_spec.rb
@@ -1,34 +1,47 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the is_string function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'is_string' do
- it "should exist" do
- expect(Puppet::Parser::Functions.function("is_string")).to eq("function_is_string")
- end
+ 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 {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_is_string([]) }.to( raise_error(Puppet::ParseError))
- end
+ it { is_expected.to run.with_params(3).and_return(false) }
+ it { is_expected.to run.with_params('3').and_return(false) }
+ it { is_expected.to run.with_params(-3).and_return(false) }
+ it { is_expected.to run.with_params('-3').and_return(false) }
- it "should return true if a string" do
- result = scope.function_is_string(["asdf"])
- expect(result).to(eq(true))
- end
+ it { is_expected.to run.with_params(3.7).and_return(false) }
+ it { is_expected.to run.with_params('3.7').and_return(false) }
+ it { is_expected.to run.with_params(-3.7).and_return(false) }
+ it { is_expected.to run.with_params('3.7').and_return(false) }
- it "should return false if an integer" do
- result = scope.function_is_string(["3"])
- expect(result).to(eq(false))
- end
+ it { is_expected.to run.with_params([]).and_return(false) }
+ it { is_expected.to run.with_params([1]).and_return(false) }
+ it { is_expected.to run.with_params({}).and_return(false) }
+ it { is_expected.to run.with_params(true).and_return(false) }
+ it { is_expected.to run.with_params(false).and_return(false) }
+ it { is_expected.to run.with_params('one').and_return(true) }
+ it { is_expected.to run.with_params('0001234').and_return(true) }
- it "should return false if a float" do
- result = scope.function_is_string(["3.23"])
- expect(result).to(eq(false))
- end
+ context 'Checking for deprecation warning' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
+ # Checking for deprecation warning, which should only be provoked when the env variable for it is set.
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params('sponge').and_return(true)
+ end
+ it 'should display no warning for deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "false"
+ scope.expects(:warning).with(includes('This method is deprecated')).never
+ is_expected.to run.with_params('bob').and_return(true)
+ end
+ end
- it "should return false if an array" do
- result = scope.function_is_string([["a","b","c"]])
- expect(result).to(eq(false))
- end
end
diff --git a/spec/functions/join_keys_to_values_spec.rb b/spec/functions/join_keys_to_values_spec.rb
index 4a9ae87..c2bae5b 100755
--- a/spec/functions/join_keys_to_values_spec.rb
+++ b/spec/functions/join_keys_to_values_spec.rb
@@ -1,40 +1,23 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the join_keys_to_values function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("join_keys_to_values")).to eq("function_join_keys_to_values")
- end
-
- it "should raise a ParseError if there are fewer than two arguments" do
- expect { scope.function_join_keys_to_values([{}]) }.to raise_error Puppet::ParseError
- end
-
- it "should raise a ParseError if there are greater than two arguments" do
- expect { scope.function_join_keys_to_values([{}, 'foo', 'bar']) }.to raise_error Puppet::ParseError
- end
-
- it "should raise a TypeError if the first argument is an array" do
- expect { scope.function_join_keys_to_values([[1,2], ',']) }.to raise_error TypeError
- end
-
- it "should raise a TypeError if the second argument is an array" do
- expect { scope.function_join_keys_to_values([{}, [1,2]]) }.to raise_error TypeError
- end
-
- it "should raise a TypeError if the second argument is a number" do
- expect { scope.function_join_keys_to_values([{}, 1]) }.to raise_error TypeError
- end
-
- it "should return an empty array given an empty hash" do
- result = scope.function_join_keys_to_values([{}, ":"])
- expect(result).to eq([])
- end
-
- it "should join hash's keys to its values" do
- result = scope.function_join_keys_to_values([{'a'=>1,2=>'foo',:b=>nil}, ":"])
- expect(result).to match_array(['a:1','2:foo','b:'])
+describe 'join_keys_to_values' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /Takes exactly two arguments/) }
+ it { is_expected.to run.with_params({}, '', '').and_raise_error(Puppet::ParseError, /Takes exactly two arguments/) }
+ it { is_expected.to run.with_params('one', '').and_raise_error(TypeError, /The first argument must be a hash/) }
+ it { is_expected.to run.with_params({}, 2).and_raise_error(TypeError, /The second argument must be a string/) }
+
+ it { is_expected.to run.with_params({}, '').and_return([]) }
+ it { is_expected.to run.with_params({}, ':').and_return([]) }
+ it { is_expected.to run.with_params({ 'key' => 'value' }, '').and_return(['keyvalue']) }
+ it { is_expected.to run.with_params({ 'key' => 'value' }, ':').and_return(['key:value']) }
+ it { is_expected.to run.with_params({ 'key' => nil }, ':').and_return(['key:']) }
+ it 'should run join_keys_to_values(<hash with multiple keys>, ":") and return the proper array' do
+ result = subject.call([{ 'key1' => 'value1', 'key2' => 'value2' }, ':'])
+ expect(result.sort).to eq(['key1:value1', 'key2:value2'].sort)
+ end
+ it 'should run join_keys_to_values(<hash with array value>, " ") and return the proper array' do
+ result = subject.call([{ 'key1' => 'value1', 'key2' => ['value2', 'value3'] }, ' '])
+ expect(result.sort).to eq(['key1 value1', 'key2 value2', 'key2 value3'].sort)
end
end
diff --git a/spec/functions/join_spec.rb b/spec/functions/join_spec.rb
index 793c36f..a300571 100755
--- a/spec/functions/join_spec.rb
+++ b/spec/functions/join_spec.rb
@@ -1,19 +1,19 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the join function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'join' 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 {
+ pending("Current implementation ignores parameters after the second.")
+ 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, /Requires array to work with/) }
+ it { is_expected.to run.with_params([], 2).and_raise_error(Puppet::ParseError, /Requires string to work with/) }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("join")).to eq("function_join")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_join([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should join an array into a string" do
- result = scope.function_join([["a","b","c"], ":"])
- expect(result).to(eq("a:b:c"))
- end
+ it { is_expected.to run.with_params([]).and_return('') }
+ it { is_expected.to run.with_params([], ':').and_return('') }
+ it { is_expected.to run.with_params(['one']).and_return('one') }
+ it { is_expected.to run.with_params(['one'], ':').and_return('one') }
+ it { is_expected.to run.with_params(['one', 'two', 'three']).and_return('onetwothree') }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], ':').and_return('one:two:three') }
end
diff --git a/spec/functions/keys_spec.rb b/spec/functions/keys_spec.rb
index f2e7d42..2e009dc 100755
--- a/spec/functions/keys_spec.rb
+++ b/spec/functions/keys_spec.rb
@@ -1,21 +1,19 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the keys function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("keys")).to eq("function_keys")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_keys([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return an array of keys when given a hash" do
- result = scope.function_keys([{'a'=>1, 'b'=>2}])
- # =~ performs 'array with same elements' (set) matching
- # For more info see RSpec::Matchers::MatchArray
- expect(result).to match_array(['a','b'])
+describe 'keys' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ 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, /Requires hash to work with/) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires hash to work with/) }
+ it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError, /Requires hash to work with/) }
+ it { is_expected.to run.with_params({}).and_return([]) }
+ it { is_expected.to run.with_params({ 'key' => 'value' }).and_return(['key']) }
+ it 'should return the array of keys' do
+ result = subject.call([{ 'key1' => 'value1', 'key2' => 'value2' }])
+ expect(result).to match_array(['key1', 'key2'])
end
end
diff --git a/spec/functions/load_module_metadata_spec.rb b/spec/functions/load_module_metadata_spec.rb
new file mode 100755
index 0000000..1a61e2c
--- /dev/null
+++ b/spec/functions/load_module_metadata_spec.rb
@@ -0,0 +1,38 @@
+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", "three").and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+ describe "when calling with valid arguments" do
+ before :each do
+ if RSpec.configuration.puppet_future
+ allow(File).to receive(:read).with(/\/stdlib\/metadata.json/, {:encoding=>"utf-8"}).and_return('{"name": "puppetlabs-stdlib"}')
+ else
+ allow(File).to receive(:read).with(/\/stdlib\/metadata.json/).and_return('{"name": "puppetlabs-stdlib"}')
+ end
+ end
+ 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('/path/to/module/metadata.json').and_return(true)
+ allow(File).to receive(:read).with('/path/to/module/metadata.json').and_return('{"name": "spencer-science"}')
+
+ result = subject.call(['science'])
+ expect(result['name']).to eq('spencer-science')
+ end
+
+ it "should fail by default if there is no metadata.json" do
+ allow(scope).to receive(:function_get_module_path).with(['science']).and_return('/path/to/module/')
+ allow(File).to receive(:exists?).with('/path/to/module/metadata.json').and_return(false)
+ expect {subject.call(['science'])}.to raise_error(Puppet::ParseError)
+ end
+
+ it "should return nil if user allows empty metadata.json" do
+ allow(scope).to receive(:function_get_module_path).with(['science']).and_return('/path/to/module/')
+ allow(File).to receive(:exists?).with('/path/to/module/metadata.json').and_return(false)
+ result = subject.call(['science', true])
+ expect(result).to eq({})
+ end
+ end
+end
diff --git a/spec/functions/loadjson_spec.rb b/spec/functions/loadjson_spec.rb
new file mode 100644
index 0000000..a00dff9
--- /dev/null
+++ b/spec/functions/loadjson_spec.rb
@@ -0,0 +1,49 @@
+require 'spec_helper'
+
+describe 'loadjson' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(ArgumentError, /wrong number of arguments/i) }
+
+ describe "when calling with valid arguments" do
+ before :each do
+ if RSpec.configuration.puppet_future
+ allow(File).to receive(:read).with(/\/stdlib\/metadata.json/, {:encoding=>"utf-8"}).and_return('{"name": "puppetlabs-stdlib"}')
+ else
+ allow(File).to receive(:read).with(/\/stdlib\/metadata.json/).and_return('{"name": "puppetlabs-stdlib"}')
+ end
+ end
+
+ context 'when a non-existing file is specified' do
+ let(:filename) { '/tmp/doesnotexist' }
+ before {
+ allow(File).to receive(:exists?).with(filename).and_return(false).once
+ allow(PSON).to receive(:load).never
+ }
+ it { is_expected.to run.with_params(filename, {'default' => 'value'}).and_return({'default' => 'value'}) }
+ end
+
+ context 'when an existing file is specified' do
+ let(:filename) { '/tmp/doesexist' }
+ let(:data) { { 'key' => 'value' } }
+ let(:json) { '{"key":"value"}' }
+ before {
+ allow(File).to receive(:exists?).with(filename).and_return(true).once
+ allow(File).to receive(:read).with(filename).and_return(json).once
+ allow(File).to receive(:read).with(filename).and_return(json).once
+ allow(PSON).to receive(:load).with(json).and_return(data).once
+ }
+ it { is_expected.to run.with_params(filename).and_return(data) }
+ end
+
+ context 'when the file could not be parsed' do
+ let(:filename) { '/tmp/doesexist' }
+ let(:json) { '{"key":"value"}' }
+ before {
+ allow(File).to receive(:exists?).with(filename).and_return(true).once
+ allow(File).to receive(:read).with(filename).and_return(json).once
+ allow(PSON).to receive(:load).with(json).once.and_raise StandardError, 'Something terrible have happened!'
+ }
+ it { is_expected.to run.with_params(filename, {'default' => 'value'}).and_return({'default' => 'value'}) }
+ end
+ end
+end
diff --git a/spec/functions/loadyaml_spec.rb b/spec/functions/loadyaml_spec.rb
index cdc3d6f..9f16a1a 100755
--- a/spec/functions/loadyaml_spec.rb
+++ b/spec/functions/loadyaml_spec.rb
@@ -1,25 +1,34 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the loadyaml function" do
- include PuppetlabsSpec::Files
+describe 'loadyaml' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(ArgumentError, /wrong number of arguments/i) }
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("loadyaml")).to eq("function_loadyaml")
+ context 'when a non-existing file is specified' do
+ let(:filename) { '/tmp/doesnotexist' }
+ before {
+ File.expects(:exists?).with(filename).returns(false).once
+ YAML.expects(:load_file).never
+ }
+ it { is_expected.to run.with_params(filename, {'default' => 'value'}).and_return({'default' => 'value'}) }
end
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_loadyaml([]) }.to raise_error(Puppet::ParseError)
+ context 'when an existing file is specified' do
+ let(:filename) { '/tmp/doesexist' }
+ let(:data) { { 'key' => 'value' } }
+ before {
+ File.expects(:exists?).with(filename).returns(true).once
+ YAML.expects(:load_file).with(filename).returns(data).once
+ }
+ it { is_expected.to run.with_params(filename).and_return(data) }
end
- it "should convert YAML file to a data structure" do
- yaml_file = tmpfilename ('yamlfile')
- File.open(yaml_file, 'w') do |fh|
- fh.write("---\n aaa: 1\n bbb: 2\n ccc: 3\n ddd: 4\n")
- end
- result = scope.function_loadyaml([yaml_file])
- expect(result).to eq({"aaa" => 1, "bbb" => 2, "ccc" => 3, "ddd" => 4 })
+ context 'when the file could not be parsed' do
+ let(:filename) { '/tmp/doesexist' }
+ before {
+ File.expects(:exists?).with(filename).returns(true).once
+ YAML.stubs(:load_file).with(filename).once.raises StandardError, 'Something terrible have happened!'
+ }
+ it { is_expected.to run.with_params(filename, {'default' => 'value'}).and_return({'default' => 'value'}) }
end
end
diff --git a/spec/functions/lstrip_spec.rb b/spec/functions/lstrip_spec.rb
index 68cca1c..981794e 100755
--- a/spec/functions/lstrip_spec.rb
+++ b/spec/functions/lstrip_spec.rb
@@ -1,28 +1,34 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the lstrip function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("lstrip")).to eq("function_lstrip")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_lstrip([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should lstrip a string" do
- result = scope.function_lstrip([" asdf"])
- expect(result).to(eq('asdf'))
- end
-
- it "should accept objects which extend String" do
- class AlsoString < String
- end
-
- value = AlsoString.new(" asdf")
- result = scope.function_lstrip([value])
- result.should(eq("asdf"))
- end
+describe 'lstrip' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ 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, /Requires either array or string to work with/) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work with/) }
+ it { is_expected.to run.with_params('').and_return('') }
+ it { is_expected.to run.with_params(' ').and_return('') }
+ it { is_expected.to run.with_params(' ').and_return('') }
+ it { is_expected.to run.with_params("\t").and_return('') }
+ it { is_expected.to run.with_params("\t ").and_return('') }
+ it { is_expected.to run.with_params('one').and_return('one') }
+ it { is_expected.to run.with_params(' one').and_return('one') }
+ it { is_expected.to run.with_params(' one').and_return('one') }
+ it { is_expected.to run.with_params("\tone").and_return('one') }
+ it { is_expected.to run.with_params("\t one").and_return('one') }
+ it { is_expected.to run.with_params('one ').and_return('one ') }
+ it { is_expected.to run.with_params(' one ').and_return('one ') }
+ it { is_expected.to run.with_params(' one ').and_return('one ') }
+ it { is_expected.to run.with_params("\tone ").and_return('one ') }
+ it { is_expected.to run.with_params("\t one ").and_return('one ') }
+ it { is_expected.to run.with_params("one \t").and_return("one \t") }
+ it { is_expected.to run.with_params(" one \t").and_return("one \t") }
+ it { is_expected.to run.with_params(" one \t").and_return("one \t") }
+ it { is_expected.to run.with_params("\tone \t").and_return("one \t") }
+ it { is_expected.to run.with_params("\t one \t").and_return("one \t") }
+ it { is_expected.to run.with_params(' o n e ').and_return('o n e ') }
+ it { is_expected.to run.with_params(AlsoString.new(' one ')).and_return('one ') }
end
diff --git a/spec/functions/max_spec.rb b/spec/functions/max_spec.rb
index c3d8a13..66fb0c8 100755
--- a/spec/functions/max_spec.rb
+++ b/spec/functions/max_spec.rb
@@ -1,27 +1,21 @@
-#! /usr/bin/env ruby -S rspec
-
require 'spec_helper'
-describe "the max function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("max")).to eq("function_max")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_max([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should be able to compare strings" do
- expect(scope.function_max(["albatross","dog","horse"])).to(eq("horse"))
- end
-
- it "should be able to compare numbers" do
- expect(scope.function_max([6,8,4])).to(eq(8))
- end
+describe 'max' 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(1).and_return(1) }
+ it { is_expected.to run.with_params(1, 2).and_return(2) }
+ it { is_expected.to run.with_params(1, 2, 3).and_return(3) }
+ it { is_expected.to run.with_params(3, 2, 1).and_return(3) }
+ it { is_expected.to run.with_params('one').and_return('one') }
+ it { is_expected.to run.with_params('one', 'two').and_return('two') }
+ it { is_expected.to run.with_params('one', 'two', 'three').and_return('two') }
+ it { is_expected.to run.with_params('three', 'two', 'one').and_return('two') }
- it "should be able to compare a number with a stringified number" do
- expect(scope.function_max([1,"2"])).to(eq("2"))
+ describe 'implementation artifacts' do
+ it { is_expected.to run.with_params(1, 'one').and_return('one') }
+ it { is_expected.to run.with_params('1', 'one').and_return('one') }
+ it { is_expected.to run.with_params('1.3e1', '1.4e0').and_return('1.4e0') }
+ it { is_expected.to run.with_params(1.3e1, 1.4e0).and_return(1.3e1) }
end
end
diff --git a/spec/functions/member_spec.rb b/spec/functions/member_spec.rb
index 1a1d7c6..527f887 100755
--- a/spec/functions/member_spec.rb
+++ b/spec/functions/member_spec.rb
@@ -1,34 +1,21 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the member function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("member")).to eq("function_member")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_member([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return true if a member is in an array" do
- result = scope.function_member([["a","b","c"], "a"])
- expect(result).to(eq(true))
- end
-
- it "should return false if a member is not in an array" do
- result = scope.function_member([["a","b","c"], "d"])
- expect(result).to(eq(false))
- end
-
- it "should return true if a member array is in an array" do
- result = scope.function_member([["a","b","c"], ["a", "b"]])
- expect(result).to(eq(true))
- end
-
- it "should return false if a member array is not in an array" do
- result = scope.function_member([["a","b","c"], ["d", "e"]])
- expect(result).to(eq(false))
- end
+describe 'member' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params([], [], []).and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params([], '').and_return(false) }
+ it { is_expected.to run.with_params([], ['']).and_return(false) }
+ it { is_expected.to run.with_params([''], '').and_return(true) }
+ it { is_expected.to run.with_params([''], ['']).and_return(true) }
+ it { is_expected.to run.with_params([], 'one').and_return(false) }
+ it { is_expected.to run.with_params([], ['one']).and_return(false) }
+ it { is_expected.to run.with_params(['one'], 'one').and_return(true) }
+ it { is_expected.to run.with_params(['one'], ['one']).and_return(true) }
+ it { is_expected.to run.with_params(['one', 'two', 'three', 'four'], ['four', 'two']).and_return(true) }
+ it { is_expected.to run.with_params(['one', 'two', 'three', 'four'], ['four', 'five']).and_return(false) }
end
diff --git a/spec/functions/merge_spec.rb b/spec/functions/merge_spec.rb
index 2abf976..7b53363 100755
--- a/spec/functions/merge_spec.rb
+++ b/spec/functions/merge_spec.rb
@@ -1,52 +1,25 @@
-#! /usr/bin/env ruby -S rspec
-
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:merge) do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- describe 'when calling merge from puppet' do
- it "should not compile when no arguments are passed" do
- skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./
- Puppet[:code] = '$x = merge()'
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /wrong number of arguments/)
- end
-
- it "should not compile when 1 argument is passed" do
- skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./
- Puppet[:code] = "$my_hash={'one' => 1}\n$x = merge($my_hash)"
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /wrong number of arguments/)
- end
- end
-
- describe 'when calling merge on the scope instance' do
- it 'should require all parameters are hashes' do
- expect { new_hash = scope.function_merge([{}, '2'])}.to raise_error(Puppet::ParseError, /unexpected argument type String/)
- expect { new_hash = scope.function_merge([{}, 2])}.to raise_error(Puppet::ParseError, /unexpected argument type Fixnum/)
- end
-
- it 'should accept empty strings as puppet undef' do
- expect { new_hash = scope.function_merge([{}, ''])}.not_to raise_error
- end
-
- it 'should be able to merge two hashes' do
- new_hash = scope.function_merge([{'one' => '1', 'two' => '1'}, {'two' => '2', 'three' => '2'}])
- expect(new_hash['one']).to eq('1')
- expect(new_hash['two']).to eq('2')
- expect(new_hash['three']).to eq('2')
- end
-
- it 'should merge multiple hashes' do
- hash = scope.function_merge([{'one' => 1}, {'one' => '2'}, {'one' => '3'}])
- expect(hash['one']).to eq('3')
- end
-
- it 'should accept empty hashes' do
- expect(scope.function_merge([{},{},{}])).to eq({})
- end
+describe 'merge' 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({}, 'two').and_raise_error(Puppet::ParseError, /unexpected argument type String/) }
+ it { is_expected.to run.with_params({}, 1).and_raise_error(Puppet::ParseError, /unexpected argument type Fixnum/) }
+ it {
+ pending 'should not special case this'
+ is_expected.to run.with_params({}).and_return({})
+ }
+ it { is_expected.to run.with_params({}, {}).and_return({}) }
+ it { is_expected.to run.with_params({}, {}, {}).and_return({}) }
+ describe 'should accept empty strings as puppet undef' do
+ it { is_expected.to run.with_params({}, '').and_return({}) }
end
+ it { is_expected.to run.with_params({ 'key' => 'value' }, {}).and_return({ 'key' => 'value' }) }
+ it { is_expected.to run.with_params({}, { 'key' => 'value' }).and_return({ 'key' => 'value' }) }
+ it { is_expected.to run.with_params({ 'key' => 'value1' }, { 'key' => 'value2' }).and_return({ 'key' => 'value2' }) }
+ it {
+ is_expected.to run \
+ .with_params({ 'key1' => 'value1' }, { 'key2' => 'value2' }, { 'key3' => 'value3' }) \
+ .and_return({ 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3' })
+ }
end
diff --git a/spec/functions/min_spec.rb b/spec/functions/min_spec.rb
index 35a0890..c840a72 100755
--- a/spec/functions/min_spec.rb
+++ b/spec/functions/min_spec.rb
@@ -1,27 +1,21 @@
-#! /usr/bin/env ruby -S rspec
-
require 'spec_helper'
-describe "the min function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("min")).to eq("function_min")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_min([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should be able to compare strings" do
- expect(scope.function_min(["albatross","dog","horse"])).to(eq("albatross"))
- end
-
- it "should be able to compare numbers" do
- expect(scope.function_min([6,8,4])).to(eq(4))
- end
+describe 'min' 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(1).and_return(1) }
+ it { is_expected.to run.with_params(1, 2).and_return(1) }
+ it { is_expected.to run.with_params(1, 2, 3).and_return(1) }
+ it { is_expected.to run.with_params(3, 2, 1).and_return(1) }
+ it { is_expected.to run.with_params('one').and_return('one') }
+ it { is_expected.to run.with_params('one', 'two').and_return('one') }
+ it { is_expected.to run.with_params('one', 'two', 'three').and_return('one') }
+ it { is_expected.to run.with_params('three', 'two', 'one').and_return('one') }
- it "should be able to compare a number with a stringified number" do
- expect(scope.function_min([1,"2"])).to(eq(1))
+ describe 'implementation artifacts' do
+ it { is_expected.to run.with_params(1, 'one').and_return(1) }
+ it { is_expected.to run.with_params('1', 'one').and_return('1') }
+ it { is_expected.to run.with_params('1.3e1', '1.4e0').and_return('1.3e1') }
+ it { is_expected.to run.with_params(1.3e1, 1.4e0).and_return(1.4e0) }
end
end
diff --git a/spec/functions/num2bool_spec.rb b/spec/functions/num2bool_spec.rb
index d0ba935..494afff 100755
--- a/spec/functions/num2bool_spec.rb
+++ b/spec/functions/num2bool_spec.rb
@@ -1,67 +1,22 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the num2bool function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("num2bool")).to eq("function_num2bool")
- end
-
- it "should raise a ParseError if there are no arguments" do
- expect { scope.function_num2bool([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should raise a ParseError if there are more than 1 arguments" do
- expect { scope.function_num2bool(["foo","bar"]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should raise a ParseError if passed something non-numeric" do
- expect { scope.function_num2bool(["xyzzy"]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return true if passed string 1" do
- result = scope.function_num2bool(["1"])
- expect(result).to(be_truthy)
- end
-
- it "should return true if passed string 1.5" do
- result = scope.function_num2bool(["1.5"])
- expect(result).to(be_truthy)
- end
-
- it "should return true if passed number 1" do
- result = scope.function_num2bool([1])
- expect(result).to(be_truthy)
- end
-
- it "should return false if passed string 0" do
- result = scope.function_num2bool(["0"])
- expect(result).to(be_falsey)
- end
-
- it "should return false if passed number 0" do
- result = scope.function_num2bool([0])
- expect(result).to(be_falsey)
- end
-
- it "should return false if passed string -1" do
- result = scope.function_num2bool(["-1"])
- expect(result).to(be_falsey)
- end
-
- it "should return false if passed string -1.5" do
- result = scope.function_num2bool(["-1.5"])
- expect(result).to(be_falsey)
- end
-
- it "should return false if passed number -1" do
- result = scope.function_num2bool([-1])
- expect(result).to(be_falsey)
- end
-
- it "should return false if passed float -1.5" do
- result = scope.function_num2bool([-1.5])
- expect(result).to(be_falsey)
- end
+describe 'num2bool' 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(1, 2).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ it { is_expected.to run.with_params('abc').and_raise_error(Puppet::ParseError, /does not look like a number/) }
+ it { is_expected.to run.with_params(1).and_return(true) }
+ it { is_expected.to run.with_params('1').and_return(true) }
+ it { is_expected.to run.with_params(1.5).and_return(true) }
+ it { is_expected.to run.with_params('1.5').and_return(true) }
+ it { is_expected.to run.with_params(-1).and_return(false) }
+ it { is_expected.to run.with_params('-1').and_return(false) }
+ it { is_expected.to run.with_params(-1.5).and_return(false) }
+ it { is_expected.to run.with_params('-1.5').and_return(false) }
+ it { is_expected.to run.with_params(0).and_return(false) }
+ it { is_expected.to run.with_params('0').and_return(false) }
+ it { is_expected.to run.with_params([]).and_return(false) }
+ it { is_expected.to run.with_params('[]').and_raise_error(Puppet::ParseError, /does not look like a number/) }
+ it { is_expected.to run.with_params({}).and_return(false) }
+ it { is_expected.to run.with_params('{}').and_raise_error(Puppet::ParseError, /does not look like a number/) }
end
diff --git a/spec/functions/parsejson_spec.rb b/spec/functions/parsejson_spec.rb
index 1dd41b9..a01f1f6 100755
--- a/spec/functions/parsejson_spec.rb
+++ b/spec/functions/parsejson_spec.rb
@@ -1,22 +1,64 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the parsejson function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'parsejson' do
+ it 'should exist' do
+ is_expected.not_to eq(nil)
+ end
- it "should exist" do
- expect(Puppet::Parser::Functions.function("parsejson")).to eq("function_parsejson")
+ 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
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_parsejson([]) }.to( raise_error(Puppet::ParseError))
+ 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
- it "should convert JSON to a data structure" do
- json = <<-EOS
-["aaa","bbb","ccc"]
-EOS
- result = scope.function_parsejson([json])
- expect(result).to(eq(['aaa','bbb','ccc']))
+ context 'with incorrect JSON data' do
+ it 'should raise an error with invalid JSON and no default' do
+ is_expected.to run.with_params('').
+ and_raise_error(PSON::ParserError)
+ 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
diff --git a/spec/functions/parseyaml_spec.rb b/spec/functions/parseyaml_spec.rb
index e5f145b..fa947ca 100755
--- a/spec/functions/parseyaml_spec.rb
+++ b/spec/functions/parseyaml_spec.rb
@@ -1,24 +1,81 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the parseyaml function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'parseyaml' do
+ it 'should exist' do
+ is_expected.not_to eq(nil)
+ end
- it "should exist" do
- expect(Puppet::Parser::Functions.function("parseyaml")).to eq("function_parseyaml")
+ 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
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_parseyaml([]) }.to( raise_error(Puppet::ParseError))
+ 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
- it "should convert YAML to a data structure" do
- yaml = <<-EOS
-- aaa
-- bbb
-- ccc
-EOS
- result = scope.function_parseyaml([yaml])
- expect(result).to(eq(['aaa','bbb','ccc']))
+ context 'on a modern ruby', :unless => RUBY_VERSION == '1.8.7' do
+ it 'should raise an error with invalid YAML and no default' do
+ is_expected.to run.with_params('["one"').
+ and_raise_error(Psych::SyntaxError)
+ end
end
+
+ context 'when running on ruby 1.8.7, which does not have Psych', :if => RUBY_VERSION == '1.8.7' do
+ it 'should raise an error with invalid YAML and no default' do
+ is_expected.to run.with_params('["one"').
+ and_raise_error(ArgumentError)
+ end
+ end
+
+ context 'with incorrect YAML data' do
+ 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
diff --git a/spec/functions/pick_default_spec.rb b/spec/functions/pick_default_spec.rb
index db10cc3..e2fc64a 100755
--- a/spec/functions/pick_default_spec.rb
+++ b/spec/functions/pick_default_spec.rb
@@ -1,58 +1,24 @@
-#!/usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the pick_default function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("pick_default")).to eq("function_pick_default")
- end
-
- it 'should return the correct value' do
- expect(scope.function_pick_default(['first', 'second'])).to eq('first')
- end
-
- it 'should return the correct value if the first value is empty' do
- expect(scope.function_pick_default(['', 'second'])).to eq('second')
- end
-
- it 'should skip empty string values' do
- expect(scope.function_pick_default(['', 'first'])).to eq('first')
- end
-
- it 'should skip :undef values' do
- expect(scope.function_pick_default([:undef, 'first'])).to eq('first')
- end
-
- it 'should skip :undefined values' do
- expect(scope.function_pick_default([:undefined, 'first'])).to eq('first')
- end
-
- it 'should return the empty string if it is the last possibility' do
- expect(scope.function_pick_default([:undef, :undefined, ''])).to eq('')
- end
-
- it 'should return :undef if it is the last possibility' do
- expect(scope.function_pick_default(['', :undefined, :undef])).to eq(:undef)
- end
-
- it 'should return :undefined if it is the last possibility' do
- expect(scope.function_pick_default([:undef, '', :undefined])).to eq(:undefined)
- end
-
- it 'should return the empty string if it is the only possibility' do
- expect(scope.function_pick_default([''])).to eq('')
- end
-
- it 'should return :undef if it is the only possibility' do
- expect(scope.function_pick_default([:undef])).to eq(:undef)
- end
-
- it 'should return :undefined if it is the only possibility' do
- expect(scope.function_pick_default([:undefined])).to eq(:undefined)
- end
-
- it 'should error if no values are passed' do
- expect { scope.function_pick_default([]) }.to raise_error(Puppet::Error, /Must receive at least one argument./)
+describe 'pick_default' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::Error, /Must receive at least one argument/) }
+
+ it { is_expected.to run.with_params('one', 'two').and_return('one') }
+ it { is_expected.to run.with_params('', 'two').and_return('two') }
+ it { is_expected.to run.with_params(:undef, 'two').and_return('two') }
+ it { is_expected.to run.with_params(:undefined, 'two').and_return('two') }
+ it { is_expected.to run.with_params(nil, 'two').and_return('two') }
+
+ [ '', :undef, :undefined, nil, {}, [], 1, 'default' ].each do |value|
+ describe "when providing #{value.inspect} as default" do
+ it { is_expected.to run.with_params('one', value).and_return('one') }
+ it { is_expected.to run.with_params([], value).and_return([]) }
+ it { is_expected.to run.with_params({}, value).and_return({}) }
+ it { is_expected.to run.with_params(value, value).and_return(value) }
+ it { is_expected.to run.with_params(:undef, value).and_return(value) }
+ it { is_expected.to run.with_params(:undefined, value).and_return(value) }
+ it { is_expected.to run.with_params(nil, value).and_return(value) }
+ end
end
end
diff --git a/spec/functions/pick_spec.rb b/spec/functions/pick_spec.rb
index 8be8f58..2c7caa8 100755
--- a/spec/functions/pick_spec.rb
+++ b/spec/functions/pick_spec.rb
@@ -1,34 +1,12 @@
-#!/usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the pick function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("pick")).to eq("function_pick")
- end
-
- it 'should return the correct value' do
- expect(scope.function_pick(['first', 'second'])).to eq('first')
- end
-
- it 'should return the correct value if the first value is empty' do
- expect(scope.function_pick(['', 'second'])).to eq('second')
- end
-
- it 'should remove empty string values' do
- expect(scope.function_pick(['', 'first'])).to eq('first')
- end
-
- it 'should remove :undef values' do
- expect(scope.function_pick([:undef, 'first'])).to eq('first')
- end
-
- it 'should remove :undefined values' do
- expect(scope.function_pick([:undefined, 'first'])).to eq('first')
- end
-
- it 'should error if no values are passed' do
- expect { scope.function_pick([]) }.to( raise_error(Puppet::ParseError, "pick(): must receive at least one non empty value"))
- end
+describe 'pick' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /must receive at least one non empty value/) }
+ it { is_expected.to run.with_params('', nil, :undef, :undefined).and_raise_error(Puppet::ParseError, /must receive at least one non empty value/) }
+ it { is_expected.to run.with_params('one', 'two').and_return('one') }
+ it { is_expected.to run.with_params('', 'two').and_return('two') }
+ it { is_expected.to run.with_params(:undef, 'two').and_return('two') }
+ it { is_expected.to run.with_params(:undefined, 'two').and_return('two') }
+ it { is_expected.to run.with_params(nil, 'two').and_return('two') }
end
diff --git a/spec/functions/prefix_spec.rb b/spec/functions/prefix_spec.rb
index 34cac53..3761022 100755
--- a/spec/functions/prefix_spec.rb
+++ b/spec/functions/prefix_spec.rb
@@ -1,28 +1,28 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the prefix function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "raises a ParseError if there is less than 1 arguments" do
- expect { scope.function_prefix([]) }.to raise_error(Puppet::ParseError, /number of arguments/)
- end
-
- it "raises an error if the first argument is not an array" do
- expect {
- scope.function_prefix([Object.new])
- }.to raise_error(Puppet::ParseError, /expected first argument to be an Array/)
- end
-
-
- it "raises an error if the second argument is not a string" do
- expect {
- scope.function_prefix([['first', 'second'], 42])
- }.to raise_error(Puppet::ParseError, /expected second argument to be a String/)
- end
-
- it "returns a prefixed array" do
- result = scope.function_prefix([['a','b','c'], 'p'])
- expect(result).to(eq(['pa','pb','pc']))
- end
+describe 'prefix' 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 {
+ pending("Current implementation ignores parameters after the second.")
+ is_expected.to run.with_params([], 'a', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /expected first argument to be an Array or a Hash/) }
+ it { is_expected.to run.with_params([], 2).and_raise_error(Puppet::ParseError, /expected second argument to be a String/) }
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(['one', 2]).and_return(['one', '2']) }
+ it { is_expected.to run.with_params([], '').and_return([]) }
+ it { is_expected.to run.with_params([''], '').and_return(['']) }
+ it { is_expected.to run.with_params(['one'], 'pre').and_return(['preone']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], 'pre').and_return(['preone', 'pretwo', 'prethree']) }
+ it { is_expected.to run.with_params({}).and_return({}) }
+ it { is_expected.to run.with_params({ 'key1' => 'value1', 2 => 3}).and_return({ 'key1' => 'value1', '2' => 3 }) }
+ it { is_expected.to run.with_params({}, '').and_return({}) }
+ it { is_expected.to run.with_params({ 'key' => 'value' }, '').and_return({ 'key' => 'value' }) }
+ it { is_expected.to run.with_params({ 'key' => 'value' }, 'pre').and_return({ 'prekey' => 'value' }) }
+ it {
+ is_expected.to run \
+ .with_params({ 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3' }, 'pre') \
+ .and_return({ 'prekey1' => 'value1', 'prekey2' => 'value2', 'prekey3' => 'value3' })
+ }
end
diff --git a/spec/functions/private_spec.rb b/spec/functions/private_spec.rb
index c70759f..a13be64 100755..100644
--- a/spec/functions/private_spec.rb
+++ b/spec/functions/private_spec.rb
@@ -1,12 +1,13 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:private) do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- subject do
- function_name = Puppet::Parser::Functions.function(:private)
- scope.method(function_name)
+describe 'private' do
+ it 'should issue a warning' do
+ scope.expects(:warning).with("private() DEPRECATED: This function will cease to function on Puppet 4; please use assert_private() before upgrading to puppet 4 for backwards-compatibility, or migrate to the new parser's typing system.")
+ begin
+ subject.call []
+ rescue
+ # ignore this
+ end
end
context "when called from inside module" do
diff --git a/spec/functions/pw_hash_spec.rb b/spec/functions/pw_hash_spec.rb
new file mode 100644
index 0000000..df5348c
--- /dev/null
+++ b/spec/functions/pw_hash_spec.rb
@@ -0,0 +1,69 @@
+require 'spec_helper'
+
+describe 'pw_hash' do
+
+ it { is_expected.not_to eq(nil) }
+
+ context 'when there are less than 3 arguments' do
+ it { is_expected.to run.with_params().and_raise_error(ArgumentError, /wrong number of arguments/i) }
+ it { is_expected.to run.with_params('password').and_raise_error(ArgumentError, /wrong number of arguments/i) }
+ it { is_expected.to run.with_params('password', 'sha-256').and_raise_error(ArgumentError, /wrong number of arguments/i) }
+ end
+
+ context 'when there are more than 3 arguments' do
+ it { is_expected.to run.with_params('password', 'sha-256', 'salt', 'extra').and_raise_error(ArgumentError, /wrong number of arguments/i) }
+ it { is_expected.to run.with_params('password', 'sha-256', 'salt', 'extra', 'extra').and_raise_error(ArgumentError, /wrong number of arguments/i) }
+ end
+
+ context 'when the first argument is not a string' do
+ it { is_expected.to run.with_params([], 'sha-256', 'salt').and_raise_error(ArgumentError, /first argument must be a string/) }
+ it { is_expected.to run.with_params({}, 'sha-256', 'salt').and_raise_error(ArgumentError, /first argument must be a string/) }
+ it { is_expected.to run.with_params(1, 'sha-256', 'salt').and_raise_error(ArgumentError, /first argument must be a string/) }
+ it { is_expected.to run.with_params(true, 'sha-256', 'salt').and_raise_error(ArgumentError, /first argument must be a string/) }
+ end
+
+ context 'when the first argument is undefined' do
+ it { is_expected.to run.with_params('', 'sha-256', 'salt').and_return(nil) }
+ it { is_expected.to run.with_params(nil, 'sha-256', 'salt').and_return(nil) }
+ end
+
+ context 'when the second argument is not a string' do
+ it { is_expected.to run.with_params('password', [], 'salt').and_raise_error(ArgumentError, /second argument must be a string/) }
+ it { is_expected.to run.with_params('password', {}, 'salt').and_raise_error(ArgumentError, /second argument must be a string/) }
+ it { is_expected.to run.with_params('password', 1, 'salt').and_raise_error(ArgumentError, /second argument must be a string/) }
+ it { is_expected.to run.with_params('password', true, 'salt').and_raise_error(ArgumentError, /second argument must be a string/) }
+ end
+
+ context 'when the second argument is not one of the supported hashing algorithms' do
+ it { is_expected.to run.with_params('password', 'no such algo', 'salt').and_raise_error(ArgumentError, /is not a valid hash type/) }
+ end
+
+ context 'when the third argument is not a string' do
+ it { is_expected.to run.with_params('password', 'sha-256', []).and_raise_error(ArgumentError, /third argument must be a string/) }
+ it { is_expected.to run.with_params('password', 'sha-256', {}).and_raise_error(ArgumentError, /third argument must be a string/) }
+ it { is_expected.to run.with_params('password', 'sha-256', 1).and_raise_error(ArgumentError, /third argument must be a string/) }
+ it { is_expected.to run.with_params('password', 'sha-256', true).and_raise_error(ArgumentError, /third argument must be a string/) }
+ end
+
+ context 'when the third argument is empty' do
+ it { is_expected.to run.with_params('password', 'sha-512', '').and_raise_error(ArgumentError, /third argument must not be empty/) }
+ end
+
+ context 'when the third argument contains invalid characters' do
+ it { is_expected.to run.with_params('password', 'sha-512', 'one%').and_raise_error(ArgumentError, /characters in salt must be in the set/) }
+ end
+
+ context 'when running on a platform with a weak String#crypt implementation' do
+ before(:each) { allow_any_instance_of(String).to receive(:crypt).with('$1$1').and_return('a bad hash') }
+
+ it { is_expected.to run.with_params('password', 'sha-512', 'salt').and_raise_error(Puppet::ParseError, /system does not support enhanced salts/) }
+ end
+
+ if RUBY_PLATFORM == 'java' or 'test'.crypt('$1$1') == '$1$1$Bp8CU9Oujr9SSEw53WV6G.'
+ describe "on systems with enhanced salts support" do
+ it { is_expected.to run.with_params('password', 'md5', 'salt').and_return('$1$salt$qJH7.N4xYta3aEG/dfqo/0') }
+ it { is_expected.to run.with_params('password', 'sha-256', 'salt').and_return('$5$salt$Gcm6FsVtF/Qa77ZKD.iwsJlCVPY0XSMgLJL0Hnww/c1') }
+ it { is_expected.to run.with_params('password', 'sha-512', 'salt').and_return('$6$salt$IxDD3jeSOb5eB1CX5LBsqZFVkJdido3OUILO5Ifz5iwMuTS4XMS130MTSuDDl3aCI6WouIL9AjRbLCelDCy.g.') }
+ end
+ end
+end
diff --git a/spec/functions/range_spec.rb b/spec/functions/range_spec.rb
index ef86f97..492cad4 100755
--- a/spec/functions/range_spec.rb
+++ b/spec/functions/range_spec.rb
@@ -1,86 +1,118 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the range function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'range' do
+ it { is_expected.not_to eq(nil) }
- it "exists" do
- expect(Puppet::Parser::Functions.function("range")).to eq("function_range")
+ describe 'signature validation in puppet3', :unless => RSpec.configuration.puppet_future do
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ it {
+ pending("Current implementation ignores parameters after the third.")
+ is_expected.to run.with_params(1, 2, 3, 4).and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params('1..2..3').and_raise_error(Puppet::ParseError, /Unable to compute range/i) }
+ it { is_expected.to run.with_params('').and_raise_error(Puppet::ParseError, /Unknown range format/i) }
end
- it "raises a ParseError if there is less than 1 arguments" do
- expect { scope.function_range([]) }.to raise_error Puppet::ParseError, /Wrong number of arguments.*0 for 1/
+ describe 'signature validation in puppet4', :if => RSpec.configuration.puppet_future do
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params().and_raise_error(ArgumentError) }
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params('').and_raise_error(ArgumentError) }
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params({}).and_raise_error(ArgumentError) }
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params([]).and_raise_error(ArgumentError) }
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params(true).and_raise_error(ArgumentError) }
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params(true).and_raise_error(ArgumentError) }
+ it { is_expected.to run.with_params(1, 2, 'foo').and_raise_error(ArgumentError) }
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params(1, 2, []).and_raise_error(ArgumentError) }
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params(1, 2, {}).and_raise_error(ArgumentError) }
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params(1, 2, true).and_raise_error(ArgumentError) }
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params(1, 2, 3, 4).and_raise_error(ArgumentError) }
+ it { pending "the puppet 4 implementation"; is_expected.to run.with_params('1..2..3').and_raise_error(ArgumentError) }
end
- describe 'with a letter range' do
- it "returns a letter range" do
- result = scope.function_range(["a","d"])
- expect(result).to eq ['a','b','c','d']
- end
-
- it "returns a letter range given a step of 1" do
- result = scope.function_range(["a","d","1"])
- expect(result).to eq ['a','b','c','d']
- end
-
- it "returns a stepped letter range" do
- result = scope.function_range(["a","d","2"])
- expect(result).to eq ['a','c']
- end
+ context 'with characters as bounds' do
+ it { is_expected.to run.with_params('d', 'a').and_return([]) }
+ it { is_expected.to run.with_params('a', 'a').and_return(['a']) }
+ it { is_expected.to run.with_params('a', 'b').and_return(['a', 'b']) }
+ it { is_expected.to run.with_params('a', 'd').and_return(['a', 'b', 'c', 'd']) }
+ it { is_expected.to run.with_params('a', 'd', 1).and_return(['a', 'b', 'c', 'd']) }
+ it { is_expected.to run.with_params('a', 'd', '1').and_return(['a', 'b', 'c', 'd']) }
+ it { is_expected.to run.with_params('a', 'd', 2).and_return(['a', 'c']) }
+ it { is_expected.to run.with_params('a', 'd', -2).and_return(['a', 'c']) }
+ it { is_expected.to run.with_params('a', 'd', 3).and_return(['a', 'd']) }
+ it { is_expected.to run.with_params('a', 'd', 4).and_return(['a']) }
+ end
- it "returns a stepped letter range given a negative step" do
- result = scope.function_range(["a","d","-2"])
- expect(result).to eq ['a','c']
- end
+ context 'with strings as bounds' do
+ it { is_expected.to run.with_params('onea', 'oned').and_return(['onea', 'oneb', 'onec', 'oned']) }
+ it { is_expected.to run.with_params('two', 'one').and_return([]) }
+ it { is_expected.to run.with_params('true', 'false').and_return([]) }
+ it { is_expected.to run.with_params('false', 'true').and_return(['false']) }
end
- describe 'with a number range' do
- it "returns a number range" do
- result = scope.function_range(["1","4"])
- expect(result).to eq [1,2,3,4]
- end
+ context 'with integers as bounds' do
+ it { is_expected.to run.with_params(4, 1).and_return([]) }
+ it { is_expected.to run.with_params(1, 1).and_return([1]) }
+ it { is_expected.to run.with_params(1, 2).and_return([1, 2]) }
+ it { is_expected.to run.with_params(1, 4).and_return([1, 2, 3, 4]) }
+ it { is_expected.to run.with_params(1, 4, 1).and_return([1, 2, 3, 4]) }
+ it { is_expected.to run.with_params(1, 4, '1').and_return([1, 2, 3, 4]) }
+ it { is_expected.to run.with_params(1, 4, 2).and_return([1, 3]) }
+ it { is_expected.to run.with_params(1, 4, -2).and_return([1, 3]) }
+ it { is_expected.to run.with_params(1, 4, 3).and_return([1, 4]) }
+ it { is_expected.to run.with_params(1, 4, 4).and_return([1]) }
+ end
- it "returns a number range given a step of 1" do
- result = scope.function_range(["1","4","1"])
- expect(result).to eq [1,2,3,4]
- end
+ context 'with integers as strings as bounds' do
+ it { is_expected.to run.with_params('4', '1').and_return([]) }
+ it { is_expected.to run.with_params('1', '1').and_return([1]) }
+ it { is_expected.to run.with_params('1', '2').and_return([1, 2]) }
+ it { is_expected.to run.with_params('1', '4').and_return([1, 2, 3, 4]) }
+ it { is_expected.to run.with_params('1', '4', 1).and_return([1, 2, 3, 4]) }
+ it { is_expected.to run.with_params('1', '4', '1').and_return([1, 2, 3, 4]) }
+ it { is_expected.to run.with_params('1', '4', 2).and_return([1, 3]) }
+ it { is_expected.to run.with_params('1', '4', -2).and_return([1, 3]) }
+ it { is_expected.to run.with_params('1', '4', 3).and_return([1, 4]) }
+ it { is_expected.to run.with_params('1', '4', 4).and_return([1]) }
+ end
- it "returns a stepped number range" do
- result = scope.function_range(["1","4","2"])
- expect(result).to eq [1,3]
- end
+ context 'with prefixed numbers as strings as bounds' do
+ it { is_expected.to run.with_params('host01', 'host04').and_return(['host01', 'host02', 'host03', 'host04']) }
+ it { is_expected.to run.with_params('01', '04').and_return([1, 2, 3, 4]) }
+ end
- it "returns a stepped number range given a negative step" do
- result = scope.function_range(["1","4","-2"])
- expect(result).to eq [1,3]
- end
+ context 'with dash-range syntax' do
+ it { is_expected.to run.with_params('4-1').and_return([]) }
+ it { is_expected.to run.with_params('1-1').and_return([1]) }
+ it { is_expected.to run.with_params('1-2').and_return([1, 2]) }
+ it { is_expected.to run.with_params('1-4').and_return([1, 2, 3, 4]) }
end
- describe 'with a numeric-like string range' do
- it "works with padded hostname like strings" do
- expected = ("host01".."host10").to_a
- expect(scope.function_range(["host01","host10"])).to eq expected
- end
+ context 'with two-dot-range syntax' do
+ it { is_expected.to run.with_params('4..1').and_return([]) }
+ it { is_expected.to run.with_params('1..1').and_return([1]) }
+ it { is_expected.to run.with_params('1..2').and_return([1, 2]) }
+ it { is_expected.to run.with_params('1..4').and_return([1, 2, 3, 4]) }
+ end
- it "coerces zero padded digits to integers" do
- expected = (0..10).to_a
- expect(scope.function_range(["00", "10"])).to eq expected
- end
+ context 'with three-dot-range syntax' do
+ it { is_expected.to run.with_params('4...1').and_return([]) }
+ it { is_expected.to run.with_params('1...1').and_return([]) }
+ it { is_expected.to run.with_params('1...2').and_return([1]) }
+ it { is_expected.to run.with_params('1...3').and_return([1, 2]) }
+ it { is_expected.to run.with_params('1...5').and_return([1, 2, 3, 4]) }
end
- describe 'with a numeric range' do
- it "returns a range of numbers" do
- expected = (1..10).to_a
- expect(scope.function_range([1,10])).to eq expected
- end
- it "returns a range of numbers with step parameter" do
- expected = (1..10).step(2).to_a
- expect(scope.function_range([1,10,2])).to eq expected
- end
- it "works with mixed numeric like strings and numeric arguments" do
- expected = (1..10).to_a
- expect(scope.function_range(['1',10])).to eq expected
- expect(scope.function_range([1,'10'])).to eq expected
- end
+ describe 'when passing mixed arguments as bounds' do
+ it {
+ pending('these bounds should not be allowed as ruby will OOM hard. e.g. `(\'host0\'..\'hosta\').to_a` has 3239930 elements on ruby 1.9, adding more \'0\'s and \'a\'s increases that exponentially')
+ is_expected.to run.with_params('0', 'a').and_raise_error(Puppet::ParseError, /cannot interpolate between numeric and non-numeric bounds/)
+ }
+ it {
+ pending('these bounds should not be allowed as ruby will OOM hard. e.g. `(\'host0\'..\'hosta\').to_a` has 3239930 elements on ruby 1.9, adding more \'0\'s and \'a\'s increases that exponentially')
+ is_expected.to run.with_params(0, 'a').and_raise_error(Puppet::ParseError, /cannot interpolate between numeric and non-numeric bounds/)
+ }
+ it {
+ pending('these bounds should not be allowed as ruby will OOM hard. e.g. `(\'host0\'..\'hosta\').to_a` has 3239930 elements on ruby 1.9, adding more \'0\'s and \'a\'s increases that exponentially')
+ is_expected.to run.with_params('h0', 'ha').and_raise_error(Puppet::ParseError, /cannot interpolate between numeric and non-numeric bounds/)
+ }
end
end
diff --git a/spec/functions/regexpescape_spec.rb b/spec/functions/regexpescape_spec.rb
new file mode 100644
index 0000000..6efa847
--- /dev/null
+++ b/spec/functions/regexpescape_spec.rb
@@ -0,0 +1,36 @@
+require 'spec_helper'
+
+describe 'regexpescape' do
+ describe 'signature validation' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ end
+
+ describe 'handling normal strings' do
+ it 'should call ruby\'s Regexp.escape function' do
+ Regexp.expects(:escape).with('regexp_string').returns('escaped_regexp_string').once
+ is_expected.to run.with_params('regexp_string').and_return('escaped_regexp_string')
+ end
+ end
+
+ describe 'handling classes derived from String' do
+ it 'should call ruby\'s Regexp.escape function' do
+ regexp_string = AlsoString.new('regexp_string')
+ Regexp.expects(:escape).with(regexp_string).returns('escaped_regexp_string').once
+ is_expected.to run.with_params(regexp_string).and_return("escaped_regexp_string")
+ end
+ end
+
+ describe 'strings in arrays handling' do
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(['one*', "two"]).and_return(['one\*', "two"]) }
+ it { is_expected.to run.with_params(['one*', 1, true, {}, "two"]).and_return(['one\*', 1, true, {}, "two"]) }
+ end
+end
diff --git a/spec/functions/reject_spec.rb b/spec/functions/reject_spec.rb
index 88a992e..4863050 100755
--- a/spec/functions/reject_spec.rb
+++ b/spec/functions/reject_spec.rb
@@ -1,20 +1,19 @@
-#!/usr/bin/env ruby
-
require 'spec_helper'
-describe "the reject function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("reject")).to eq("function_reject")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_reject([]) }.to( raise_error(Puppet::ParseError))
- end
+describe 'reject' 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([], 'pattern', 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
- it "should reject contents from an array" do
- result = scope.function_reject([["1111", "aaabbb","bbbccc","dddeee"], "bbb"])
- expect(result).to(eq(["1111", "dddeee"]))
- end
+ it {
+ pending("reject does not actually check this, and raises NoMethodError instead")
+ is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError, /first argument not an array/)
+ }
+ it {
+ pending("reject does not actually check this, and raises NoMethodError instead")
+ is_expected.to run.with_params(1, 'two').and_raise_error(Puppet::ParseError, /first argument not an array/)
+ }
+ it { is_expected.to run.with_params([], 'two').and_return([]) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], 'two').and_return(['one', 'three']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], 't(wo|hree)').and_return(['one']) }
end
diff --git a/spec/functions/reverse_spec.rb b/spec/functions/reverse_spec.rb
index 1f04794..e00dee9 100755
--- a/spec/functions/reverse_spec.rb
+++ b/spec/functions/reverse_spec.rb
@@ -1,28 +1,31 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the reverse function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'reverse' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ 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, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(['a']).and_return(['a']) }
+ it { is_expected.to run.with_params(['one']).and_return(['one']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three']).and_return(['three', 'two', 'one']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three', 'four']).and_return(['four', 'three', 'two', 'one']) }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("reverse")).to eq("function_reverse")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_reverse([]) }.to( raise_error(Puppet::ParseError))
- end
+ it { is_expected.to run.with_params('').and_return('') }
+ it { is_expected.to run.with_params('a').and_return('a') }
+ it { is_expected.to run.with_params('abc').and_return('cba') }
+ it { is_expected.to run.with_params('abcd').and_return('dcba') }
- it "should reverse a string" do
- result = scope.function_reverse(["asdfghijkl"])
- expect(result).to(eq('lkjihgfdsa'))
- end
-
- it "should accept objects which extend String" do
- class AlsoString < String
+ context 'when using a class extending String' do
+ it 'should call its reverse method' do
+ value = AlsoString.new('asdfghjkl')
+ value.expects(:reverse).returns('foo')
+ expect(subject).to run.with_params(value).and_return('foo')
end
-
- value = AlsoString.new('asdfghjkl')
- result = scope.function_reverse([value])
- result.should(eq('lkjhgfdsa'))
end
end
diff --git a/spec/functions/rstrip_spec.rb b/spec/functions/rstrip_spec.rb
index f6b4838..d2efac8 100755
--- a/spec/functions/rstrip_spec.rb
+++ b/spec/functions/rstrip_spec.rb
@@ -1,33 +1,34 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the rstrip function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("rstrip")).to eq("function_rstrip")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_rstrip([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should rstrip a string" do
- result = scope.function_rstrip(["asdf "])
- expect(result).to(eq('asdf'))
- end
-
- it "should rstrip each element in an array" do
- result = scope.function_rstrip([["a ","b ", "c "]])
- expect(result).to(eq(['a','b','c']))
- end
-
- it "should accept objects which extend String" do
- class AlsoString < String
- end
-
- value = AlsoString.new('asdf ')
- result = scope.function_rstrip([value])
- result.should(eq('asdf'))
- end
+describe 'rstrip' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ 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, /Requires either array or string to work with/) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work with/) }
+ it { is_expected.to run.with_params('').and_return('') }
+ it { is_expected.to run.with_params(' ').and_return('') }
+ it { is_expected.to run.with_params(' ').and_return('') }
+ it { is_expected.to run.with_params("\t").and_return('') }
+ it { is_expected.to run.with_params("\t ").and_return('') }
+ it { is_expected.to run.with_params('one').and_return('one') }
+ it { is_expected.to run.with_params(' one').and_return(' one') }
+ it { is_expected.to run.with_params(' one').and_return(' one') }
+ it { is_expected.to run.with_params("\tone").and_return("\tone") }
+ it { is_expected.to run.with_params("\t one").and_return("\t one") }
+ it { is_expected.to run.with_params('one ').and_return('one') }
+ it { is_expected.to run.with_params(' one ').and_return(' one') }
+ it { is_expected.to run.with_params(' one ').and_return(' one') }
+ it { is_expected.to run.with_params("\tone ").and_return("\tone") }
+ it { is_expected.to run.with_params("\t one ").and_return("\t one") }
+ it { is_expected.to run.with_params("one\t").and_return('one') }
+ it { is_expected.to run.with_params(" one\t").and_return(' one') }
+ it { is_expected.to run.with_params(" one\t").and_return(' one') }
+ it { is_expected.to run.with_params("\tone\t").and_return("\tone") }
+ it { is_expected.to run.with_params("\t one\t").and_return("\t one") }
+ it { is_expected.to run.with_params(' o n e ').and_return(' o n e') }
+ it { is_expected.to run.with_params(AlsoString.new(' one ')).and_return(' one') }
end
diff --git a/spec/functions/seeded_rand_spec.rb b/spec/functions/seeded_rand_spec.rb
new file mode 100644
index 0000000..38e134e
--- /dev/null
+++ b/spec/functions/seeded_rand_spec.rb
@@ -0,0 +1,53 @@
+require 'spec_helper'
+
+describe 'seeded_rand' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params().and_raise_error(ArgumentError, /wrong number of arguments/i) }
+ it { is_expected.to run.with_params(1).and_raise_error(ArgumentError, /wrong number of arguments/i) }
+ it { is_expected.to run.with_params(0, '').and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+ it { is_expected.to run.with_params(1.5, '').and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+ it { is_expected.to run.with_params(-10, '').and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+ it { is_expected.to run.with_params("-10", '').and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+ it { is_expected.to run.with_params("string", '').and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+ it { is_expected.to run.with_params([], '').and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+ it { is_expected.to run.with_params({}, '').and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+ it { is_expected.to run.with_params(1, 1).and_raise_error(ArgumentError, /second argument must be a string/) }
+ it { is_expected.to run.with_params(1, []).and_raise_error(ArgumentError, /second argument must be a string/) }
+ it { is_expected.to run.with_params(1, {}).and_raise_error(ArgumentError, /second argument must be a string/) }
+
+ it "provides a random number strictly less than the given max" do
+ expect(seeded_rand(3, 'seed')).to satisfy {|n| n.to_i < 3 }
+ end
+
+ it "provides a random number greater or equal to zero" do
+ expect(seeded_rand(3, 'seed')).to satisfy {|n| n.to_i >= 0 }
+ end
+
+ it "provides the same 'random' value on subsequent calls for the same host" do
+ expect(seeded_rand(10, 'seed')).to eql(seeded_rand(10, 'seed'))
+ end
+
+ it "allows seed to control the random value on a single host" do
+ first_random = seeded_rand(1000, 'seed1')
+ second_different_random = seeded_rand(1000, 'seed2')
+
+ expect(first_random).not_to eql(second_different_random)
+ end
+
+ it "should not return different values for different hosts" do
+ val1 = seeded_rand(1000, 'foo', :host => "first.host.com")
+ val2 = seeded_rand(1000, 'foo', :host => "second.host.com")
+
+ expect(val1).to eql(val2)
+ end
+
+ def seeded_rand(max, seed, args = {})
+ host = args[:host] || '127.0.0.1'
+
+ # workaround not being able to use let(:facts) because some tests need
+ # multiple different hostnames in one context
+ scope.stubs(:lookupvar).with("::fqdn", {}).returns(host)
+
+ scope.function_seeded_rand([max, seed])
+ end
+end
diff --git a/spec/functions/shell_escape_spec.rb b/spec/functions/shell_escape_spec.rb
new file mode 100644
index 0000000..3061dec
--- /dev/null
+++ b/spec/functions/shell_escape_spec.rb
@@ -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
diff --git a/spec/functions/shell_join_spec.rb b/spec/functions/shell_join_spec.rb
new file mode 100644
index 0000000..6815f7c
--- /dev/null
+++ b/spec/functions/shell_join_spec.rb
@@ -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
diff --git a/spec/functions/shell_split_spec.rb b/spec/functions/shell_split_spec.rb
new file mode 100644
index 0000000..beeb977
--- /dev/null
+++ b/spec/functions/shell_split_spec.rb
@@ -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
diff --git a/spec/functions/shuffle_spec.rb b/spec/functions/shuffle_spec.rb
index a62c1fb..ebc3a73 100755
--- a/spec/functions/shuffle_spec.rb
+++ b/spec/functions/shuffle_spec.rb
@@ -1,33 +1,33 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the shuffle function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'shuffle' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ 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, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("shuffle")).to eq("function_shuffle")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_shuffle([]) }.to( raise_error(Puppet::ParseError))
- end
+ context 'when running with a specific seed' do
+ # make tests deterministic
+ before(:each) { srand(2) }
- it "should shuffle a string and the result should be the same size" do
- result = scope.function_shuffle(["asdf"])
- expect(result.size).to(eq(4))
- end
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(['a']).and_return(['a']) }
+ it { is_expected.to run.with_params(['one']).and_return(['one']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three']).and_return(['two', 'one', 'three']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three', 'four']).and_return(['four', 'three', 'two', 'one']) }
- it "should shuffle a string but the sorted contents should still be the same" do
- result = scope.function_shuffle(["adfs"])
- expect(result.split("").sort.join("")).to(eq("adfs"))
- end
+ it { is_expected.to run.with_params('').and_return('') }
+ it { is_expected.to run.with_params('a').and_return('a') }
+ it { is_expected.to run.with_params('abc').and_return('bac') }
+ it { is_expected.to run.with_params('abcd').and_return('dcba') }
- it "should accept objects which extend String" do
- class AlsoString < String
+ context 'when using a class extending String' do
+ it { is_expected.to run.with_params(AlsoString.new('asdfghjkl')).and_return('lkhdsfajg') }
end
-
- value = AlsoString.new('asdf')
- result = scope.function_shuffle([value])
- result.size.should(eq(4))
end
end
diff --git a/spec/functions/size_spec.rb b/spec/functions/size_spec.rb
index 18eb48f..c0047ee 100755
--- a/spec/functions/size_spec.rb
+++ b/spec/functions/size_spec.rb
@@ -1,24 +1,35 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the size function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'size' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ 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(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, 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 "should exist" do
- expect(Puppet::Parser::Functions.function("size")).to eq("function_size")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_size([]) }.to( raise_error(Puppet::ParseError))
- end
+ 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 "should return the size of a string" do
- result = scope.function_size(["asdf"])
- expect(result).to(eq(4))
- end
+ 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) }
+ it { is_expected.to run.with_params('abcd').and_return(4) }
- it "should return the size of an array" do
- result = scope.function_size([["a","b","c"]])
- expect(result).to(eq(3))
+ context 'when using a class extending String' do
+ it 'should call its size method' do
+ value = AlsoString.new('asdfghjkl')
+ value.expects(:size).returns('foo')
+ expect(subject).to run.with_params(value).and_return('foo')
+ end
end
end
diff --git a/spec/functions/sort_spec.rb b/spec/functions/sort_spec.rb
index 4c2a66c..9abd039 100755
--- a/spec/functions/sort_spec.rb
+++ b/spec/functions/sort_spec.rb
@@ -1,24 +1,24 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the sort function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("sort")).to eq("function_sort")
- end
-
- it "should raise a ParseError if there is not 1 arguments" do
- expect { scope.function_sort(['','']) }.to( raise_error(Puppet::ParseError))
+describe 'sort' do
+ describe 'signature validation' 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([], 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ it { pending('stricter input checking'); is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /requires string or array/) }
+ it { pending('stricter input checking'); is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /requires string or array/) }
+ it { pending('stricter input checking'); is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /requires string or array/) }
end
- it "should sort an array" do
- result = scope.function_sort([["a","c","b"]])
- expect(result).to(eq(['a','b','c']))
+ context 'when called with an array' do
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(['a']).and_return(['a']) }
+ it { is_expected.to run.with_params(['c', 'b', 'a']).and_return(['a', 'b', 'c']) }
end
- it "should sort a string" do
- result = scope.function_sort(["acb"])
- expect(result).to(eq('abc'))
+ context 'when called with a string' do
+ it { is_expected.to run.with_params('').and_return('') }
+ it { is_expected.to run.with_params('a').and_return('a') }
+ it { is_expected.to run.with_params('cbda').and_return('abcd') }
end
end
diff --git a/spec/functions/squeeze_spec.rb b/spec/functions/squeeze_spec.rb
index cd0eb37..7f09c30 100755
--- a/spec/functions/squeeze_spec.rb
+++ b/spec/functions/squeeze_spec.rb
@@ -1,24 +1,44 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the squeeze function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'squeeze' 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(1).and_raise_error(NoMethodError) }
+ it { is_expected.to run.with_params({}).and_raise_error(NoMethodError) }
+ it { is_expected.to run.with_params(true).and_raise_error(NoMethodError) }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("squeeze")).to eq("function_squeeze")
+ context 'when squeezing a single string' do
+ it { is_expected.to run.with_params('').and_return('') }
+ it { is_expected.to run.with_params('a').and_return('a') }
+ it { is_expected.to run.with_params('aaaaaaaaa').and_return('a') }
+ it { is_expected.to run.with_params('aaaaaaaaa', 'a').and_return('a') }
+ it { is_expected.to run.with_params('aaaaaaaaabbbbbbbbbbcccccccccc', 'b-c').and_return('aaaaaaaaabc') }
end
- it "should raise a ParseError if there is less than 2 arguments" do
- expect { scope.function_squeeze([]) }.to( raise_error(Puppet::ParseError))
+ context 'when squeezing values in an array' do
+ it {
+ is_expected.to run \
+ .with_params(['', 'a', 'aaaaaaaaa', 'aaaaaaaaabbbbbbbbbbcccccccccc']) \
+ .and_return( ['', 'a', 'a', 'abc'])
+ }
+ it {
+ is_expected.to run \
+ .with_params(['', 'a', 'aaaaaaaaa', 'aaaaaaaaabbbbbbbbbbcccccccccc'], 'a') \
+ .and_return( ['', 'a', 'a', 'abbbbbbbbbbcccccccccc'])
+ }
+ it {
+ is_expected.to run \
+ .with_params(['', 'a', 'aaaaaaaaa', 'aaaaaaaaabbbbbbbbbbcccccccccc'], 'b-c') \
+ .and_return( ['', 'a', 'aaaaaaaaa', 'aaaaaaaaabc'])
+ }
end
- it "should squeeze a string" do
- result = scope.function_squeeze(["aaabbbbcccc"])
- expect(result).to(eq('abc'))
- end
-
- it "should squeeze all elements in an array" do
- result = scope.function_squeeze([["aaabbbbcccc","dddfff"]])
- expect(result).to(eq(['abc','df']))
+ context 'when using a class extending String' do
+ it 'should call its squeeze method' do
+ value = AlsoString.new('aaaaaaaaa')
+ value.expects(:squeeze).returns('foo')
+ expect(subject).to run.with_params(value).and_return('foo')
+ end
end
end
diff --git a/spec/functions/str2bool_spec.rb b/spec/functions/str2bool_spec.rb
index 1d205d7..7d8c47c 100755
--- a/spec/functions/str2bool_spec.rb
+++ b/spec/functions/str2bool_spec.rb
@@ -1,31 +1,23 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the str2bool function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'str2bool' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params('true', 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /Unknown type of boolean given/) }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("str2bool")).to eq("function_str2bool")
+ describe 'when testing values that mean "true"' do
+ [ 'TRUE','1', 't', 'y', 'true', 'yes', true ].each do |value|
+ it { is_expected.to run.with_params(value).and_return(true) }
+ end
end
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_str2bool([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should convert string 'true' to true" do
- result = scope.function_str2bool(["true"])
- expect(result).to(eq(true))
- end
-
- it "should convert string 'undef' to false" do
- result = scope.function_str2bool(["undef"])
- expect(result).to(eq(false))
- end
-
- it "should return the boolean it was called with" do
- result = scope.function_str2bool([true])
- expect(result).to(eq(true))
- result = scope.function_str2bool([false])
- expect(result).to(eq(false))
+ describe 'when testing values that mean "false"' do
+ [ 'FALSE','', '0', 'f', 'n', 'false', 'no', false, 'undef', 'undefined' ].each do |value|
+ it { is_expected.to run.with_params(value).and_return(false) }
+ end
end
end
diff --git a/spec/functions/str2saltedsha512_spec.rb b/spec/functions/str2saltedsha512_spec.rb
index ab7f57f..2e1e818 100755
--- a/spec/functions/str2saltedsha512_spec.rb
+++ b/spec/functions/str2saltedsha512_spec.rb
@@ -1,45 +1,17 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the str2saltedsha512 function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'str2saltedsha512' 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('password', 2).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires a String argument/) }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("str2saltedsha512")).to eq("function_str2saltedsha512")
- end
-
- it "should raise a ParseError if there is less than 1 argument" do
- expect { scope.function_str2saltedsha512([]) }.to( raise_error(Puppet::ParseError) )
- end
-
- it "should raise a ParseError if there is more than 1 argument" do
- expect { scope.function_str2saltedsha512(['foo', 'bar', 'baz']) }.to( raise_error(Puppet::ParseError) )
- end
-
- it "should return a salted-sha512 password hash 136 characters in length" do
- result = scope.function_str2saltedsha512(["password"])
- expect(result.length).to(eq(136))
- end
-
- it "should raise an error if you pass a non-string password" do
- expect { scope.function_str2saltedsha512([1234]) }.to( raise_error(Puppet::ParseError) )
- end
-
- it "should generate a valid password" do
- # Allow the function to generate a password based on the string 'password'
- password_hash = scope.function_str2saltedsha512(["password"])
-
- # Separate the Salt and Password from the Password Hash
- salt = password_hash[0..7]
- password = password_hash[8..-1]
-
- # Convert the Salt and Password from Hex to Binary Data
- str_salt = Array(salt.lines).pack('H*')
- str_password = Array(password.lines).pack('H*')
+ context 'when running with a specific seed' do
+ # make tests deterministic
+ before(:each) { srand(2) }
- # Combine the Binary Salt with 'password' and compare the end result
- saltedpass = Digest::SHA512.digest(str_salt + 'password')
- result = (str_salt + saltedpass).unpack('H*')[0]
- expect(result).to eq(password_hash)
+ it { is_expected.to run.with_params('').and_return('0f8a612f4eeed08e47b3875d00f33c5688f7926298f2d9b5fe19d1323f910bc78b6f7b5892596d2fabaa65e7a8d99b3768c102610cf0432c4827eee01f09451e3fae4f7a') }
+ it { is_expected.to run.with_params('password').and_return('0f8a612f43134376566c5707718d600effcfb17581fc9d3fa64d7f447dfda317c174ffdb498d2c5bd5c2075dab41c9d7ada5afbdc6b55354980eb5ba61802371e6b64956') }
+ it { is_expected.to run.with_params('verylongpassword').and_return('0f8a612f7a448537540e062daa8621f9bae326ca8ccb899e1bdb10e7c218cebfceae2530b856662565fdc4d81e986fc50cfbbc46d50436610ed9429ff5e43f2c45b5d039') }
end
end
diff --git a/spec/functions/strftime_spec.rb b/spec/functions/strftime_spec.rb
index ebec54b..e76774a 100755
--- a/spec/functions/strftime_spec.rb
+++ b/spec/functions/strftime_spec.rb
@@ -1,9 +1,6 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the strftime function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
+describe 'strftime' do
it "should exist" do
expect(Puppet::Parser::Functions.function("strftime")).to eq("function_strftime")
end
diff --git a/spec/functions/strip_spec.rb b/spec/functions/strip_spec.rb
index 4ac8daf..689b6dd 100755
--- a/spec/functions/strip_spec.rb
+++ b/spec/functions/strip_spec.rb
@@ -1,27 +1,34 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the strip function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("strip")).to eq("function_strip")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_strip([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should strip a string" do
- result = scope.function_strip([" ab cd "])
- expect(result).to(eq('ab cd'))
- end
-
- it "should accept objects which extend String" do
- class AlsoString < String
- end
-
- value = AlsoString.new(' as df ')
- result = scope.function_strip([value])
- result.should(eq('as df'))
- end
+describe 'strip' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ 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, /Requires either array or string to work with/) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work with/) }
+ it { is_expected.to run.with_params('').and_return('') }
+ it { is_expected.to run.with_params(' ').and_return('') }
+ it { is_expected.to run.with_params(' ').and_return('') }
+ it { is_expected.to run.with_params("\t").and_return('') }
+ it { is_expected.to run.with_params("\t ").and_return('') }
+ it { is_expected.to run.with_params('one').and_return('one') }
+ it { is_expected.to run.with_params(' one').and_return('one') }
+ it { is_expected.to run.with_params(' one').and_return('one') }
+ it { is_expected.to run.with_params("\tone").and_return('one') }
+ it { is_expected.to run.with_params("\t one").and_return('one') }
+ it { is_expected.to run.with_params('one ').and_return('one') }
+ it { is_expected.to run.with_params(' one ').and_return('one') }
+ it { is_expected.to run.with_params(' one ').and_return('one') }
+ it { is_expected.to run.with_params("\tone ").and_return('one') }
+ it { is_expected.to run.with_params("\t one ").and_return('one') }
+ it { is_expected.to run.with_params("one \t").and_return('one') }
+ it { is_expected.to run.with_params(" one \t").and_return('one') }
+ it { is_expected.to run.with_params(" one \t").and_return('one') }
+ it { is_expected.to run.with_params("\tone \t").and_return('one') }
+ it { is_expected.to run.with_params("\t one \t").and_return('one') }
+ it { is_expected.to run.with_params(' o n e ').and_return('o n e') }
+ it { is_expected.to run.with_params(AlsoString.new(' one ')).and_return('one') }
end
diff --git a/spec/functions/suffix_spec.rb b/spec/functions/suffix_spec.rb
index c7783c6..efba4ab 100755
--- a/spec/functions/suffix_spec.rb
+++ b/spec/functions/suffix_spec.rb
@@ -1,27 +1,38 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the suffix function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "raises a ParseError if there is less than 1 arguments" do
- expect { scope.function_suffix([]) }.to raise_error(Puppet::ParseError, /number of arguments/)
- end
-
- it "raises an error if the first argument is not an array" do
- expect {
- scope.function_suffix([Object.new])
- }.to raise_error(Puppet::ParseError, /expected first argument to be an Array/)
- end
-
- it "raises an error if the second argument is not a string" do
- expect {
- scope.function_suffix([['first', 'second'], 42])
- }.to raise_error(Puppet::ParseError, /expected second argument to be a String/)
- end
-
- it "returns a suffixed array" do
- result = scope.function_suffix([['a','b','c'], 'p'])
- expect(result).to(eq(['ap','bp','cp']))
- end
+describe 'suffix' 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 {
+ pending("Current implementation ignores parameters after the second.")
+ is_expected.to run.with_params([], 'a', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /expected first argument to be an Array/) }
+ it { is_expected.to run.with_params([], 2).and_raise_error(Puppet::ParseError, /expected second argument to be a String/) }
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(['one', 2]).and_return(['one', '2']) }
+ it { is_expected.to run.with_params([], '').and_return([]) }
+ it { is_expected.to run.with_params([''], '').and_return(['']) }
+ it { is_expected.to run.with_params(['one'], 'post').and_return(['onepost']) }
+ it { is_expected.to run.with_params(['one', 'two', 'three'], 'post').and_return(['onepost', 'twopost', 'threepost']) }
+ it {
+ is_expected.to run.with_params({}).and_return({})
+ }
+ it {
+ is_expected.to run.with_params({ 'key1' => 'value1', 2 => 3}).and_return({ 'key1' => 'value1', '2' => 3 })
+ }
+ it {
+ is_expected.to run.with_params({}, '').and_return({})
+ }
+ it {
+ is_expected.to run.with_params({ 'key' => 'value' }, '').and_return({ 'key' => 'value' })
+ }
+ it {
+ is_expected.to run.with_params({ 'key' => 'value' }, 'post').and_return({ 'keypost' => 'value' })
+ }
+ it {
+ is_expected.to run \
+ .with_params({ 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3' }, 'post') \
+ .and_return({ 'key1post' => 'value1', 'key2post' => 'value2', 'key3post' => 'value3' })
+ }
end
diff --git a/spec/functions/swapcase_spec.rb b/spec/functions/swapcase_spec.rb
index 791d1df..c175a15 100755
--- a/spec/functions/swapcase_spec.rb
+++ b/spec/functions/swapcase_spec.rb
@@ -1,28 +1,40 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the swapcase function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("swapcase")).to eq("function_swapcase")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_swapcase([]) }.to( raise_error(Puppet::ParseError))
+describe 'swapcase' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params('a', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ describe 'with strings as inputs' do
+ it { is_expected.to run.with_params('').and_return('') }
+ it { is_expected.to run.with_params('one').and_return('ONE') }
+ it { is_expected.to run.with_params('ONE').and_return('one') }
+ it { is_expected.to run.with_params('oNe').and_return('OnE') }
end
-
- it "should swapcase a string" do
- result = scope.function_swapcase(["aaBBccDD"])
- expect(result).to(eq('AAbbCCdd'))
+ describe 'with arrays as inputs' do
+ it { is_expected.to run.with_params([]).and_return([]) }
+ describe 'only containing strings' do
+ it { is_expected.to run.with_params(['']).and_return(['']) }
+ it { is_expected.to run.with_params(['one']).and_return(['ONE']) }
+ it { is_expected.to run.with_params(['ONE']).and_return(['one']) }
+ it { is_expected.to run.with_params(['oNe']).and_return(['OnE']) }
+ it { is_expected.to run.with_params(['one', 'ONE']).and_return(['ONE', 'one']) }
+ it { is_expected.to run.with_params(['ONE', 'OnE']).and_return(['one', 'oNe']) }
+ it { is_expected.to run.with_params(['oNe', 'one']).and_return(['OnE', 'ONE']) }
+ end
+ describe 'containing mixed types' do
+ it { is_expected.to run.with_params(['OnE', {}]).and_return(['oNe', {}]) }
+ it { is_expected.to run.with_params(['OnE', 1]).and_return(['oNe', 1]) }
+ it { is_expected.to run.with_params(['OnE', []]).and_return(['oNe', []]) }
+ it { is_expected.to run.with_params(['OnE', ['two']]).and_return(['oNe', ['two']]) }
+ end
end
-
it "should accept objects which extend String" do
- class AlsoString < String
- end
-
- value = AlsoString.new("aaBBccDD")
- result = scope.function_swapcase([value])
- result.should(eq("AAbbCCdd"))
+ is_expected.to run.with_params(AlsoString.new("OnE")).and_return('oNe')
end
end
diff --git a/spec/functions/time_spec.rb b/spec/functions/time_spec.rb
index 6e22515..d157939 100755
--- a/spec/functions/time_spec.rb
+++ b/spec/functions/time_spec.rb
@@ -1,29 +1,21 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the time function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'time' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params('a', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
- it "should exist" do
- expect(Puppet::Parser::Functions.function("time")).to eq("function_time")
- end
-
- it "should raise a ParseError if there is more than 2 arguments" do
- expect { scope.function_time(['','']) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return a number" do
- result = scope.function_time([])
- expect(result).to be_an(Integer)
- end
-
- it "should be higher then when I wrote this test" do
- result = scope.function_time([])
- expect(result).to(be > 1311953157)
- end
-
- it "should be lower then 1.5 trillion" do
- result = scope.function_time([])
- expect(result).to(be < 1500000000)
+ context 'when running at a specific time' do
+ before(:each) {
+ # get a value before stubbing the function
+ test_time = Time.utc(2006, 10, 13, 8, 15, 11)
+ Time.expects(:new).with().returns(test_time).once
+ }
+ it { is_expected.to run.with_params().and_return(1160727311) }
+ it { is_expected.to run.with_params('').and_return(1160727311) }
+ it { is_expected.to run.with_params([]).and_return(1160727311) }
+ it { is_expected.to run.with_params({}).and_return(1160727311) }
+ it { is_expected.to run.with_params('foo').and_return(1160727311) }
+ it { is_expected.to run.with_params('UTC').and_return(1160727311) }
+ it { is_expected.to run.with_params('America/New_York').and_return(1160727311) }
end
end
diff --git a/spec/functions/to_bytes_spec.rb b/spec/functions/to_bytes_spec.rb
index 0f6ade9..2be23ff 100755
--- a/spec/functions/to_bytes_spec.rb
+++ b/spec/functions/to_bytes_spec.rb
@@ -1,83 +1,72 @@
-#! /usr/bin/env ruby -S rspec
-
require 'spec_helper'
-describe "the to_bytes function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("to_bytes")).to eq("function_to_bytes")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_to_bytes([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should convert kB to B" do
- result = scope.function_to_bytes(["4 kB"])
- expect(result).to(eq(4096))
- end
-
- it "should convert MB to B" do
- result = scope.function_to_bytes(["4 MB"])
- expect(result).to(eq(4194304))
- end
-
- it "should convert GB to B" do
- result = scope.function_to_bytes(["4 GB"])
- expect(result).to(eq(4294967296))
- end
-
- it "should convert TB to B" do
- result = scope.function_to_bytes(["4 TB"])
- expect(result).to(eq(4398046511104))
- end
-
- it "should convert PB to B" do
- result = scope.function_to_bytes(["4 PB"])
- expect(result).to(eq(4503599627370496))
- end
-
- it "should convert PB to B" do
- result = scope.function_to_bytes(["4 EB"])
- expect(result).to(eq(4611686018427387904))
- end
-
- it "should work without B in unit" do
- result = scope.function_to_bytes(["4 k"])
- expect(result).to(eq(4096))
- end
-
- it "should work without a space before unit" do
- result = scope.function_to_bytes(["4k"])
- expect(result).to(eq(4096))
- end
-
- it "should work without a unit" do
- result = scope.function_to_bytes(["5678"])
- expect(result).to(eq(5678))
- end
-
- it "should convert fractions" do
- result = scope.function_to_bytes(["1.5 kB"])
- expect(result).to(eq(1536))
- end
-
- it "should convert scientific notation" do
- result = scope.function_to_bytes(["1.5e2 B"])
- expect(result).to(eq(150))
- end
-
- it "should do nothing with a positive number" do
- result = scope.function_to_bytes([5678])
- expect(result).to(eq(5678))
- end
-
- it "should should raise a ParseError if input isn't a number" do
- expect { scope.function_to_bytes(["foo"]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should should raise a ParseError if prefix is unknown" do
- expect { scope.function_to_bytes(["5 uB"]) }.to( raise_error(Puppet::ParseError))
+describe 'to_bytes' 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('1', 'extras').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ it { is_expected.to run.with_params([]).and_raise_error(TypeError, /(can't convert|no implicit conversion of) Array (in)?to String/) }
+ it { is_expected.to run.with_params({}).and_raise_error(TypeError, /(can't convert|no implicit conversion of) Hash (in)?to String/) }
+ it { is_expected.to run.with_params(true).and_raise_error(TypeError, /(can't convert|no implicit conversion of) (TrueClass|true) (in)?to String/) }
+
+ describe 'when passing numbers' do
+ it { is_expected.to run.with_params(0).and_return(0) }
+ it { is_expected.to run.with_params(1).and_return(1) }
+ it { is_expected.to run.with_params(-1).and_return(-1) }
+ it { is_expected.to run.with_params(1.1).and_return(1.1) }
+ it { is_expected.to run.with_params(-1.1).and_return(-1.1) }
+ end
+
+ describe 'when passing numbers as strings' do
+ describe 'without a unit' do
+ it { is_expected.to run.with_params('1').and_return(1) }
+ it { is_expected.to run.with_params('-1').and_return(-1) }
+ # these are so wrong
+ it { is_expected.to run.with_params('1.1').and_return(1) }
+ it { is_expected.to run.with_params('-1.1').and_return(-1) }
+ end
+
+ describe 'with a unit' do
+ it { is_expected.to run.with_params('1k').and_return(1024) }
+ it { is_expected.to run.with_params('-1kB').and_return(-1024) }
+ it { is_expected.to run.with_params('1k').and_return(1024) }
+ it { is_expected.to run.with_params('1M').and_return(1024*1024) }
+ it { is_expected.to run.with_params('1G').and_return(1024*1024*1024) }
+ it { is_expected.to run.with_params('1T').and_return(1024*1024*1024*1024) }
+ it { is_expected.to run.with_params('1P').and_return(1024*1024*1024*1024*1024) }
+ it { is_expected.to run.with_params('1E').and_return(1024*1024*1024*1024*1024*1024) }
+ it { is_expected.to run.with_params('1.5e3M').and_return(1572864000) }
+
+ it { is_expected.to run.with_params('4k').and_return(4*1024) }
+ it { is_expected.to run.with_params('-4kB').and_return(4*-1024) }
+ it { is_expected.to run.with_params('4k').and_return(4*1024) }
+ it { is_expected.to run.with_params('4M').and_return(4*1024*1024) }
+ it { is_expected.to run.with_params('4G').and_return(4*1024*1024*1024) }
+ it { is_expected.to run.with_params('4T').and_return(4*1024*1024*1024*1024) }
+ it { is_expected.to run.with_params('4P').and_return(4*1024*1024*1024*1024*1024) }
+ it { is_expected.to run.with_params('4E').and_return(4*1024*1024*1024*1024*1024*1024) }
+
+ # these are so wrong
+ it { is_expected.to run.with_params('1.0001 k').and_return(1024) }
+ it { is_expected.to run.with_params('-1.0001 kB').and_return(-1024) }
+ end
+
+ describe 'with a unknown unit' do
+ it { is_expected.to run.with_params('1KB').and_raise_error(Puppet::ParseError, /Unknown prefix/) }
+ it { is_expected.to run.with_params('1K').and_raise_error(Puppet::ParseError, /Unknown prefix/) }
+ it { is_expected.to run.with_params('1mb').and_raise_error(Puppet::ParseError, /Unknown prefix/) }
+ it { is_expected.to run.with_params('1m').and_raise_error(Puppet::ParseError, /Unknown prefix/) }
+ it { is_expected.to run.with_params('1%').and_raise_error(Puppet::ParseError, /Unknown prefix/) }
+ it { is_expected.to run.with_params('1 p').and_raise_error(Puppet::ParseError, /Unknown prefix/) }
+ end
+ end
+
+ # these are so wrong
+ describe 'when passing random stuff' do
+ it { is_expected.to run.with_params('-1....1').and_return(-1) }
+ it { is_expected.to run.with_params('-1.e.e.e.1').and_return(-1) }
+ it { is_expected.to run.with_params('-1+1').and_return(-1) }
+ it { is_expected.to run.with_params('1-1').and_return(1) }
+ it { is_expected.to run.with_params('1 kaboom').and_return(1024) }
+ it { is_expected.to run.with_params('kaboom').and_return(0) }
end
end
diff --git a/spec/functions/try_get_value_spec.rb b/spec/functions/try_get_value_spec.rb
new file mode 100644
index 0000000..38c0efd
--- /dev/null
+++ b/spec/functions/try_get_value_spec.rb
@@ -0,0 +1,100 @@
+require 'spec_helper'
+
+describe 'try_get_value' do
+
+ let(:data) do
+ {
+ 'a' => {
+ 'g' => '2',
+ 'e' => [
+ 'f0',
+ 'f1',
+ {
+ 'x' => {
+ 'y' => 'z'
+ }
+ },
+ 'f3',
+ ]
+ },
+ 'b' => true,
+ 'c' => false,
+ 'd' => '1',
+ }
+ end
+
+ context 'single values' do
+ it 'should exist' do
+ is_expected.not_to eq(nil)
+ end
+
+ it 'should be able to return a single value' do
+ is_expected.to run.with_params('test').and_return('test')
+ end
+
+ it 'should use the default value if data is a single value and path is present' do
+ is_expected.to run.with_params('test', 'path', 'default').and_return('default')
+ end
+
+ it 'should return default if there is no data' do
+ is_expected.to run.with_params(nil, nil, 'default').and_return('default')
+ end
+
+ it 'should be able to use data structures as default values' do
+ is_expected.to run.with_params('test', 'path', data).and_return(data)
+ end
+ end
+
+ context 'structure values' do
+ it 'should be able to extracts a single hash value' do
+ is_expected.to run.with_params(data, 'd', 'default').and_return('1')
+ end
+
+ it 'should be able to extract a deeply nested hash value' do
+ is_expected.to run.with_params(data, 'a/g', 'default').and_return('2')
+ end
+
+ it 'should return the default value if the path is not found' do
+ is_expected.to run.with_params(data, 'missing', 'default').and_return('default')
+ end
+
+ it 'should return the default value if the path is too long' do
+ is_expected.to run.with_params(data, 'a/g/c/d', 'default').and_return('default')
+ end
+
+ it 'should support an array index in the path' do
+ is_expected.to run.with_params(data, 'a/e/1', 'default').and_return('f1')
+ end
+
+ it 'should return the default value if an array index is not a number' do
+ is_expected.to run.with_params(data, 'a/b/c', 'default').and_return('default')
+ end
+
+ it 'should return the default value if and index is out of array length' do
+ is_expected.to run.with_params(data, 'a/e/5', 'default').and_return('default')
+ end
+
+ it 'should be able to path though both arrays and hashes' do
+ is_expected.to run.with_params(data, 'a/e/2/x/y', 'default').and_return('z')
+ end
+
+ it 'should be able to return "true" value' do
+ is_expected.to run.with_params(data, 'b', 'default').and_return(true)
+ is_expected.to run.with_params(data, 'm', true).and_return(true)
+ end
+
+ it 'should be able to return "false" value' do
+ is_expected.to run.with_params(data, 'c', 'default').and_return(false)
+ is_expected.to run.with_params(data, 'm', false).and_return(false)
+ end
+
+ it 'should return "nil" if value is not found and no default value is provided' do
+ is_expected.to run.with_params(data, 'a/1').and_return(nil)
+ end
+
+ it 'should be able to use a custom path separator' do
+ is_expected.to run.with_params(data, 'a::g', 'default', '::').and_return('2')
+ is_expected.to run.with_params(data, 'a::c', 'default', '::').and_return('default')
+ end
+ end
+end
diff --git a/spec/functions/type3x_spec.rb b/spec/functions/type3x_spec.rb
index d21236a..c3eb1de 100644
--- a/spec/functions/type3x_spec.rb
+++ b/spec/functions/type3x_spec.rb
@@ -1,8 +1,6 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the type3x function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'type3x' do
it "should exist" do
expect(Puppet::Parser::Functions.function("type3x")).to eq("function_type3x")
end
diff --git a/spec/functions/type_of_spec.rb b/spec/functions/type_of_spec.rb
new file mode 100644
index 0000000..cc9ef78
--- /dev/null
+++ b/spec/functions/type_of_spec.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+if ENV["FUTURE_PARSER"] == 'yes'
+ describe 'type_of' do
+ pending 'teach rspec-puppet to load future-only functions under 3.7.5' do
+ it { is_expected.not_to eq(nil) }
+ end
+ end
+end
+
+if Puppet.version.to_f >= 4.0
+ describe 'type_of' 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('', '').and_raise_error(ArgumentError) }
+
+ it 'gives the type of a string' do
+ expect(subject.call({}, 'hello world')).to be_kind_of(Puppet::Pops::Types::PStringType)
+ end
+
+ it 'gives the type of an integer' do
+ expect(subject.call({}, 5)).to be_kind_of(Puppet::Pops::Types::PIntegerType)
+ end
+ end
+end
diff --git a/spec/functions/type_spec.rb b/spec/functions/type_spec.rb
index b683fcf..4288df0 100755
--- a/spec/functions/type_spec.rb
+++ b/spec/functions/type_spec.rb
@@ -1,8 +1,6 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the type function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+describe 'type' do
it "should exist" do
expect(Puppet::Parser::Functions.function("type")).to eq("function_type")
end
diff --git a/spec/functions/union_spec.rb b/spec/functions/union_spec.rb
index 706f4cb..cfd38b6 100755
--- a/spec/functions/union_spec.rb
+++ b/spec/functions/union_spec.rb
@@ -1,19 +1,24 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the union function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("union")).to eq("function_union")
- end
-
- it "should raise a ParseError if there are fewer than 2 arguments" do
- expect { scope.function_union([]) }.to( raise_error(Puppet::ParseError) )
+describe 'union' do
+ describe 'argument checking' 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', []).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 "should join two arrays together" do
- result = scope.function_union([["a","b","c"],["b","c","d"]])
- expect(result).to(eq(["a","b","c","d"]))
- end
+ it { is_expected.to run.with_params([], []).and_return([]) }
+ it { is_expected.to run.with_params([], ['one']).and_return(['one']) }
+ it { is_expected.to run.with_params(['one'], []).and_return(['one']) }
+ it { is_expected.to run.with_params(['one'], ['one']).and_return(['one']) }
+ it { is_expected.to run.with_params(['one'], ['two']).and_return(['one', 'two']) }
+ 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/unique_spec.rb b/spec/functions/unique_spec.rb
index 7cd3a56..24257a0 100755
--- a/spec/functions/unique_spec.rb
+++ b/spec/functions/unique_spec.rb
@@ -1,33 +1,27 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the unique function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("unique")).to eq("function_unique")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_unique([]) }.to( raise_error(Puppet::ParseError))
+describe 'unique' do
+ describe 'signature validation' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params([], 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
end
- it "should remove duplicate elements in a string" do
- result = scope.function_unique(["aabbc"])
- expect(result).to(eq('abc'))
+ context 'when called with an array' do
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(['a']).and_return(['a']) }
+ it { is_expected.to run.with_params(['a', 'b', 'a']).and_return(['a', 'b']) }
end
- it "should remove duplicate elements in an array" do
- result = scope.function_unique([["a","a","b","b","c"]])
- expect(result).to(eq(['a','b','c']))
- end
-
- it "should accept objects which extend String" do
- class AlsoString < String
- end
-
- value = AlsoString.new('aabbc')
- result = scope.function_unique([value])
- result.should(eq('abc'))
+ context 'when called with a string' do
+ it { is_expected.to run.with_params('').and_return('') }
+ it { is_expected.to run.with_params('a').and_return('a') }
+ it { is_expected.to run.with_params('aaba').and_return('ab') }
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/upcase_spec.rb b/spec/functions/upcase_spec.rb
index 3cf8b05..3b7b02d 100755
--- a/spec/functions/upcase_spec.rb
+++ b/spec/functions/upcase_spec.rb
@@ -1,33 +1,26 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the upcase function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("upcase")).to eq("function_upcase")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_upcase([]) }.to( raise_error(Puppet::ParseError))
+describe 'upcase' do
+ describe 'signature validation' 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(1).and_raise_error(Puppet::ParseError, /Requires an array, hash or object that responds to upcase/) }
+ it { is_expected.to run.with_params([1]).and_raise_error(Puppet::ParseError, /Requires an array, hash or object that responds to upcase/) }
end
- it "should upcase a string" do
- result = scope.function_upcase(["abc"])
- expect(result).to(eq('ABC'))
+ describe 'normal string handling' do
+ it { is_expected.to run.with_params("abc").and_return("ABC") }
+ it { is_expected.to run.with_params("Abc").and_return("ABC") }
+ it { is_expected.to run.with_params("ABC").and_return("ABC") }
end
- it "should do nothing if a string is already upcase" do
- result = scope.function_upcase(["ABC"])
- expect(result).to(eq('ABC'))
+ describe 'handling classes derived from String' do
+ it { is_expected.to run.with_params(AlsoString.new("ABC")).and_return("ABC") }
end
- it "should accept objects which extend String" do
- class AlsoString < String
- end
-
- value = AlsoString.new('abc')
- result = scope.function_upcase([value])
- result.should(eq('ABC'))
+ describe 'strings in arrays handling' do
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(["One", "twO"]).and_return(["ONE", "TWO"]) }
end
end
diff --git a/spec/functions/uriescape_spec.rb b/spec/functions/uriescape_spec.rb
index 2321e5a..f05ec08 100755
--- a/spec/functions/uriescape_spec.rb
+++ b/spec/functions/uriescape_spec.rb
@@ -1,33 +1,36 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the uriescape function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("uriescape")).to eq("function_uriescape")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_uriescape([]) }.to( raise_error(Puppet::ParseError))
+describe 'uriescape' do
+ describe 'signature validation' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+ it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
end
- it "should uriescape a string" do
- result = scope.function_uriescape([":/?#[]@!$&'()*+,;= \"{}"])
- expect(result).to(eq(':/?%23[]@!$&\'()*+,;=%20%22%7B%7D'))
- end
-
- it "should do nothing if a string is already safe" do
- result = scope.function_uriescape(["ABCdef"])
- expect(result).to(eq('ABCdef'))
+ describe 'handling normal strings' do
+ it 'should call ruby\'s URI.escape function' do
+ URI.expects(:escape).with('uri_string').returns('escaped_uri_string').once
+ is_expected.to run.with_params('uri_string').and_return('escaped_uri_string')
+ end
end
- it "should accept objects which extend String" do
- class AlsoString < String
+ describe 'handling classes derived from String' do
+ it 'should call ruby\'s URI.escape function' do
+ uri_string = AlsoString.new('uri_string')
+ URI.expects(:escape).with(uri_string).returns('escaped_uri_string').once
+ is_expected.to run.with_params(uri_string).and_return("escaped_uri_string")
end
+ end
- value = AlsoString.new('abc')
- result = scope.function_uriescape([value])
- result.should(eq('abc'))
+ describe 'strings in arrays handling' do
+ it { is_expected.to run.with_params([]).and_return([]) }
+ it { is_expected.to run.with_params(["one}", "two"]).and_return(["one%7D", "two"]) }
+ it { is_expected.to run.with_params(["one}", 1, true, {}, "two"]).and_return(["one%7D", 1, true, {}, "two"]) }
end
end
diff --git a/spec/functions/validate_absolute_path_spec.rb b/spec/functions/validate_absolute_path_spec.rb
index 36c836b..9397da5 100755
--- a/spec/functions/validate_absolute_path_spec.rb
+++ b/spec/functions/validate_absolute_path_spec.rb
@@ -1,67 +1,43 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:validate_absolute_path) do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- # The subject of these examples is the method itself.
- subject do
- # This makes sure the function is loaded within each test
- function_name = Puppet::Parser::Functions.function(:validate_absolute_path)
- scope.method(function_name)
+describe 'validate_absolute_path' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
end
- describe "Valid Paths" do
- def self.valid_paths
- %w{
- C:/
- C:\\
- C:\\WINDOWS\\System32
- C:/windows/system32
- X:/foo/bar
- X:\\foo\\bar
- /var/tmp
- /var/lib/puppet
- /var/opt/../lib/puppet
- }
- end
+ # Checking for deprecation warning
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params('c:/')
+ end
- context "Without Puppet::Util.absolute_path? (e.g. Puppet <= 2.6)" do
- before :each do
- # The intent here is to mock Puppet to behave like Puppet 2.6 does.
- # Puppet 2.6 does not have the absolute_path? method. This is only a
- # convenience test, stdlib should be run with the Puppet 2.6.x in the
- # $LOAD_PATH in addition to 2.7.x and master.
- Puppet::Util.expects(:respond_to?).with(:absolute_path?).returns(false)
- end
- valid_paths.each do |path|
- it "validate_absolute_path(#{path.inspect}) should not fail" do
- expect { subject.call [path] }.not_to raise_error
- end
- end
- valid_paths do
- it "validate_absolute_path(#{valid_paths.inspect}) should not fail" do
- expect { subject.call [valid_paths] }.not_to raise_error
- end
- end
- end
+ describe 'signature validation' 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) }
+ end
- context "Puppet without mocking" do
- valid_paths.each do |path|
- it "validate_absolute_path(#{path.inspect}) should not fail" do
- expect { subject.call [path] }.not_to raise_error
- end
- end
- valid_paths do
- it "validate_absolute_path(#{valid_paths.inspect}) should not fail" do
- expect { subject.call [valid_paths] }.not_to raise_error
- end
- end
+ describe "valid paths handling" do
+ %w{
+ C:/
+ C:\\
+ C:\\WINDOWS\\System32
+ C:/windows/system32
+ X:/foo/bar
+ X:\\foo\\bar
+ \\\\host\\windows
+ //host/windows
+ /
+ /var/tmp
+ /var/opt/../lib/puppet
+ }.each do |path|
+ it { is_expected.to run.with_params(path) }
+ it { is_expected.to run.with_params(['/tmp', path]) }
end
end
- describe 'Invalid paths' do
- context 'Garbage inputs' do
+ describe 'invalid path handling' do
+ context 'garbage inputs' do
[
nil,
[ nil ],
@@ -70,33 +46,26 @@ describe Puppet::Parser::Functions.function(:validate_absolute_path) do
{ },
'',
].each do |path|
- it "validate_absolute_path(#{path.inspect}) should fail" do
- expect { subject.call [path] }.to raise_error Puppet::ParseError
- end
+ it { is_expected.to run.with_params(path).and_raise_error(Puppet::ParseError, /is not an absolute path/) }
+ it { is_expected.to run.with_params([path]).and_raise_error(Puppet::ParseError, /is not an absolute path/) }
+ it { is_expected.to run.with_params(['/tmp', path]).and_raise_error(Puppet::ParseError, /is not an absolute path/) }
end
end
- context 'Relative paths' do
- def self.rel_paths
- %w{
- relative1
- .
- ..
- ./foo
- ../foo
- etc/puppetlabs/puppet
- opt/puppet/bin
- }
- end
- rel_paths.each do |path|
- it "validate_absolute_path(#{path.inspect}) should fail" do
- expect { subject.call [path] }.to raise_error Puppet::ParseError
- end
- end
- rel_paths do
- it "validate_absolute_path(#{rel_paths.inspect}) should fail" do
- expect { subject.call [rel_paths] }.to raise_error Puppet::ParseError
- end
+ context 'relative paths' do
+ %w{
+ relative1
+ .
+ ..
+ ./foo
+ ../foo
+ etc/puppetlabs/puppet
+ opt/puppet/bin
+ relative\\windows
+ }.each do |path|
+ it { is_expected.to run.with_params(path).and_raise_error(Puppet::ParseError, /is not an absolute path/) }
+ it { is_expected.to run.with_params([path]).and_raise_error(Puppet::ParseError, /is not an absolute path/) }
+ it { is_expected.to run.with_params(['/tmp', path]).and_raise_error(Puppet::ParseError, /is not an absolute path/) }
end
end
end
diff --git a/spec/functions/validate_array_spec.rb b/spec/functions/validate_array_spec.rb
index 4b31cfd..409b3dc 100755
--- a/spec/functions/validate_array_spec.rb
+++ b/spec/functions/validate_array_spec.rb
@@ -1,38 +1,37 @@
-#! /usr/bin/env ruby -S rspec
-
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:validate_array) do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
- describe 'when calling validate_array from puppet' do
-
- %w{ true false }.each do |the_string|
- it "should not compile when #{the_string} is a string" do
- Puppet[:code] = "validate_array('#{the_string}')"
- expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not an Array/)
- end
+describe 'validate_array' do
- it "should not compile when #{the_string} is a bare word" do
- Puppet[:code] = "validate_array(#{the_string})"
- expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not an Array/)
- end
+ describe 'signature validation' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
end
+ it { is_expected.not_to eq(nil) }
+ # Checking for deprecation warning
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params([])
+ end
+ it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
- it "should compile when multiple array arguments are passed" do
- Puppet[:code] = <<-'ENDofPUPPETcode'
- $foo = [ ]
- $bar = [ 'one', 'two' ]
- validate_array($foo, $bar)
- ENDofPUPPETcode
- scope.compiler.compile
+ describe 'valid inputs' do
+ it { is_expected.to run.with_params([]) }
+ it { is_expected.to run.with_params(['one']) }
+ it { is_expected.to run.with_params([], ['two']) }
+ it { is_expected.to run.with_params(['one'], ['two']) }
end
- it "should not compile when an undef variable is passed" do
- Puppet[:code] = <<-'ENDofPUPPETcode'
- $foo = undef
- validate_array($foo)
- ENDofPUPPETcode
- expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not an Array/)
+ describe 'invalid inputs' do
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /is not an Array/) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /is not an Array/) }
+ it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /is not an Array/) }
+ it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /is not an Array/) }
+ it { is_expected.to run.with_params([], {}).and_raise_error(Puppet::ParseError, /is not an Array/) }
+ it { is_expected.to run.with_params([], 1).and_raise_error(Puppet::ParseError, /is not an Array/) }
+ it { is_expected.to run.with_params([], true).and_raise_error(Puppet::ParseError, /is not an Array/) }
+ it { is_expected.to run.with_params([], 'one').and_raise_error(Puppet::ParseError, /is not an Array/) }
end
end
end
+
diff --git a/spec/functions/validate_augeas_spec.rb b/spec/functions/validate_augeas_spec.rb
index c695ba2..4236649 100755
--- a/spec/functions/validate_augeas_spec.rb
+++ b/spec/functions/validate_augeas_spec.rb
@@ -1,49 +1,29 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:validate_augeas), :if => Puppet.features.augeas? do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- # The subject of these examplres is the method itself.
- subject do
- # This makes sure the function is loaded within each test
- function_name = Puppet::Parser::Functions.function(:validate_augeas)
- scope.method(function_name)
- end
-
- context 'Using Puppet::Parser::Scope.new' do
-
- describe 'Garbage inputs' do
- inputs = [
- [ nil ],
- [ [ nil ] ],
- [ { 'foo' => 'bar' } ],
- [ { } ],
- [ '' ],
- [ "one", "one", "MSG to User", "4th arg" ],
- ]
-
- inputs.each do |input|
- it "validate_augeas(#{input.inspect}) should fail" do
- expect { subject.call [input] }.to raise_error Puppet::ParseError
- end
- end
+describe 'validate_augeas' do
+ unless Puppet.features.augeas?
+ skip "ruby-augeas not installed"
+ else
+ describe 'signature validation' 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('', '', [], '', 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ it { is_expected.to run.with_params('one', 'one', 'MSG to User', '4th arg').and_raise_error(NoMethodError) }
end
- describe 'Valid inputs' do
+ describe 'valid inputs' do
inputs = [
[ "root:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns' ],
[ "proc /proc proc nodev,noexec,nosuid 0 0\n", 'Fstab.lns'],
]
inputs.each do |input|
- it "validate_augeas(#{input.inspect}) should not fail" do
- expect { subject.call input }.not_to raise_error
- end
+ it { is_expected.to run.with_params(*input) }
end
end
- describe "Valid inputs which should raise an exception without a message" do
+ describe 'valid inputs which fail augeas validation' do
# The intent here is to make sure valid inputs raise exceptions when they
# don't specify an error message to display. This is the behvior in
# 2.2.x and prior.
@@ -53,14 +33,12 @@ describe Puppet::Parser::Functions.function(:validate_augeas), :if => Puppet.fea
]
inputs.each do |input|
- it "validate_augeas(#{input.inspect}) should fail" do
- expect { subject.call input }.to raise_error /validate_augeas.*?matched less than it should/
- end
+ it { is_expected.to run.with_params(*input).and_raise_error(Puppet::ParseError, /validate_augeas.*?matched less than it should/) }
end
end
- describe "Nicer Error Messages" do
- # The intent here is to make sure the function returns the 3rd argument
+ describe "when specifying nice error messages" do
+ # The intent here is to make sure the function returns the 4th argument
# in the exception thrown
inputs = [
[ "root:x:0:0:root\n", 'Passwd.lns', [], 'Failed to validate passwd content' ],
@@ -68,35 +46,29 @@ describe Puppet::Parser::Functions.function(:validate_augeas), :if => Puppet.fea
]
inputs.each do |input|
- it "validate_augeas(#{input.inspect}) should fail" do
- expect { subject.call input }.to raise_error /#{input[2]}/
- end
+ it { is_expected.to run.with_params(*input).and_raise_error(Puppet::ParseError, /#{input[3]}/) }
end
end
- describe "Passing simple unit tests" do
+ describe "matching additional tests" do
inputs = [
[ "root:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns', ['$file/foobar']],
[ "root:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns', ['$file/root/shell[.="/bin/sh"]', 'foobar']],
]
inputs.each do |input|
- it "validate_augeas(#{input.inspect}) should fail" do
- expect { subject.call input }.not_to raise_error
- end
+ it { is_expected.to run.with_params(*input) }
end
end
- describe "Failing simple unit tests" do
+ describe "failing additional tests" do
inputs = [
[ "foobar:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns', ['$file/foobar']],
[ "root:x:0:0:root:/root:/bin/sh\n", 'Passwd.lns', ['$file/root/shell[.="/bin/sh"]', 'foobar']],
]
inputs.each do |input|
- it "validate_augeas(#{input.inspect}) should fail" do
- expect { subject.call input }.to raise_error /testing path/
- end
+ it { is_expected.to run.with_params(*input).and_raise_error(Puppet::ParseError, /testing path/) }
end
end
end
diff --git a/spec/functions/validate_bool_spec.rb b/spec/functions/validate_bool_spec.rb
index a352d3b..3074d88 100755
--- a/spec/functions/validate_bool_spec.rb
+++ b/spec/functions/validate_bool_spec.rb
@@ -1,51 +1,36 @@
-#! /usr/bin/env ruby -S rspec
-
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:validate_bool) do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
- describe 'when calling validate_bool from puppet' do
-
- %w{ true false }.each do |the_string|
-
- it "should not compile when #{the_string} is a string" do
- Puppet[:code] = "validate_bool('#{the_string}')"
- expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a boolean/)
- end
-
- it "should compile when #{the_string} is a bare word" do
- Puppet[:code] = "validate_bool(#{the_string})"
- scope.compiler.compile
- end
-
- end
+describe 'validate_bool' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
- it "should not compile when an arbitrary string is passed" do
- Puppet[:code] = 'validate_bool("jeff and dan are awesome")'
- expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a boolean/)
- end
+ # Checking for deprecation warning
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params(true)
+ end
- it "should not compile when no arguments are passed" do
- Puppet[:code] = 'validate_bool()'
- expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /wrong number of arguments/)
- end
+ describe 'signature validation' 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) }
+ end
- it "should compile when multiple boolean arguments are passed" do
- Puppet[:code] = <<-'ENDofPUPPETcode'
- $foo = true
- $bar = false
- validate_bool($foo, $bar, true, false)
- ENDofPUPPETcode
- scope.compiler.compile
- end
+ describe 'acceptable values' do
+ it { is_expected.to run.with_params(true) }
+ it { is_expected.to run.with_params(false) }
+ it { is_expected.to run.with_params(true, false, false, true) }
+ end
- it "should compile when multiple boolean arguments are passed" do
- Puppet[:code] = <<-'ENDofPUPPETcode'
- $foo = true
- $bar = false
- validate_bool($foo, $bar, true, false, 'jeff')
- ENDofPUPPETcode
- expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a boolean/)
- end
+ describe 'validation failures' do
+ it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /is not a boolean/) }
+ it { is_expected.to run.with_params(true, 'one').and_raise_error(Puppet::ParseError, /is not a boolean/) }
+ it { is_expected.to run.with_params('one', false).and_raise_error(Puppet::ParseError, /is not a boolean/) }
+ it { is_expected.to run.with_params("true").and_raise_error(Puppet::ParseError, /is not a boolean/) }
+ it { is_expected.to run.with_params("false").and_raise_error(Puppet::ParseError, /is not a boolean/) }
+ it { is_expected.to run.with_params(true, "false").and_raise_error(Puppet::ParseError, /is not a boolean/) }
+ it { is_expected.to run.with_params("true", false).and_raise_error(Puppet::ParseError, /is not a boolean/) }
+ it { is_expected.to run.with_params("true", false, false, false, false, false).and_raise_error(Puppet::ParseError, /is not a boolean/) }
end
end
diff --git a/spec/functions/validate_cmd_spec.rb b/spec/functions/validate_cmd_spec.rb
index 7cb9782..ab0cbc9 100755
--- a/spec/functions/validate_cmd_spec.rb
+++ b/spec/functions/validate_cmd_spec.rb
@@ -1,85 +1,35 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-TESTEXE = File.exists?('/usr/bin/test') ? '/usr/bin/test' : '/bin/test'
-TOUCHEXE = File.exists?('/usr/bin/touch') ? '/usr/bin/touch' : '/bin/touch'
-
-describe Puppet::Parser::Functions.function(:validate_cmd) do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- subject do
- function_name = Puppet::Parser::Functions.function(:validate_cmd)
- scope.method(function_name)
+describe 'validate_cmd' do
+ let(:touch) { File.exists?('/usr/bin/touch') ? '/usr/bin/touch' : '/bin/touch' }
+
+ describe 'signature validation' 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('', '', '', 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ it {
+ pending('should implement stricter type checking')
+ is_expected.to run.with_params([], '', '').and_raise_error(Puppet::ParseError, /content must be a string/)
+ }
+ it {
+ pending('should implement stricter type checking')
+ is_expected.to run.with_params('', [], '').and_raise_error(Puppet::ParseError, /checkscript must be a string/)
+ }
+ it {
+ pending('should implement stricter type checking')
+ is_expected.to run.with_params('', '', []).and_raise_error(Puppet::ParseError, /custom error message must be a string/)
+ }
end
- context 'with no % placeholder' do
- describe "with an explicit failure message" do
- it "prints the failure message on error" do
- expect {
- subject.call ['', '/bin/false', 'failure message!']
- }.to raise_error Puppet::ParseError, /failure message!/
- end
- end
-
- describe "on validation failure" do
- it "includes the command error output" do
- expect {
- subject.call ['', "#{TOUCHEXE} /cant/touch/this"]
- }.to raise_error Puppet::ParseError, /(cannot touch|o such file or)/
- end
-
- it "includes the command return value" do
- expect {
- subject.call ['', '/cant/run/this']
- }.to raise_error Puppet::ParseError, /returned 1\b/
- end
- end
-
- describe "when performing actual validation" do
- it "can positively validate file content" do
- expect { subject.call ["non-empty", "#{TESTEXE} -s"] }.to_not raise_error
- end
-
- it "can negatively validate file content" do
- expect {
- subject.call ["", "#{TESTEXE} -s"]
- }.to raise_error Puppet::ParseError, /failed to validate.*test -s/
- end
+ context 'when validation fails' do
+ context 'with % placeholder' do
+ it { is_expected.to run.with_params('', "#{touch} % /no/such/file").and_raise_error(Puppet::ParseError, /Execution of '#{touch} \S+ \/no\/such\/file' returned 1:.*(cannot touch|o such file or)/) }
+ it { is_expected.to run.with_params('', "#{touch} % /no/such/file", 'custom error').and_raise_error(Puppet::ParseError, /custom error/) }
end
- end
-
- context 'with % placeholder' do
- describe "with an explicit failure message" do
- it "prints the failure message on error" do
- expect {
- subject.call ['', '/bin/false % -f', 'failure message!']
- }.to raise_error Puppet::ParseError, /failure message!/
- end
- end
- describe "on validation failure" do
- it "includes the command error output" do
- expect {
- subject.call ['', "#{TOUCHEXE} /cant/touch/this"]
- }.to raise_error Puppet::ParseError, /(cannot touch|o such file or)/
- end
-
- it "includes the command return value" do
- expect {
- subject.call ['', '/cant/run/this % -z']
- }.to raise_error Puppet::ParseError, /Execution of '\/cant\/run\/this .+ -z' returned 1/
- end
- end
-
- describe "when performing actual validation" do
- it "can positively validate file content" do
- expect { subject.call ["non-empty", "#{TESTEXE} -s %"] }.to_not raise_error
- end
-
- it "can negatively validate file content" do
- expect {
- subject.call ["", "#{TESTEXE} -s %"]
- }.to raise_error Puppet::ParseError, /failed to validate.*test -s/
- end
+ context 'without % placeholder' do
+ it { is_expected.to run.with_params('', "#{touch} /no/such/file").and_raise_error(Puppet::ParseError, /Execution of '#{touch} \/no\/such\/file \S+' returned 1:.*(cannot touch|o such file or)/) }
+ it { is_expected.to run.with_params('', "#{touch} /no/such/file", 'custom error').and_raise_error(Puppet::ParseError, /custom error/) }
end
end
end
diff --git a/spec/functions/validate_email_address_spec.rb b/spec/functions/validate_email_address_spec.rb
new file mode 100644
index 0000000..7628383
--- /dev/null
+++ b/spec/functions/validate_email_address_spec.rb
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe 'validate_email_address' do
+ describe 'signature validation' 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) }
+ end
+
+ describe 'valid inputs' do
+ it { is_expected.to run.with_params('bob@gmail.com') }
+ it { is_expected.to run.with_params('alice+puppetlabs.com@gmail.com') }
+ end
+
+ describe 'invalid inputs' do
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /is not a valid email/) }
+ it { is_expected.to run.with_params('bob@gmail.com', {}).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('bob@gmail.com', true).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('bob@gmail.com', 'one').and_raise_error(Puppet::ParseError, /is not a valid email/) }
+ end
+end
diff --git a/spec/functions/validate_hash_spec.rb b/spec/functions/validate_hash_spec.rb
index a0c35c2..7533abe 100755
--- a/spec/functions/validate_hash_spec.rb
+++ b/spec/functions/validate_hash_spec.rb
@@ -1,43 +1,38 @@
-#! /usr/bin/env ruby -S rspec
-
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:validate_hash) do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- describe 'when calling validate_hash from puppet' do
+describe 'validate_hash' do
+ describe 'signature validation' 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) }
- %w{ true false }.each do |the_string|
-
- it "should not compile when #{the_string} is a string" do
- Puppet[:code] = "validate_hash('#{the_string}')"
- expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a Hash/)
+ describe 'check for deprecation warning' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
end
-
- it "should not compile when #{the_string} is a bare word" do
- Puppet[:code] = "validate_hash(#{the_string})"
- expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a Hash/)
+ # Checking for deprecation warning
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params({'key' => 'value'})
end
-
end
- it "should compile when multiple hash arguments are passed" do
- Puppet[:code] = <<-'ENDofPUPPETcode'
- $foo = {}
- $bar = { 'one' => 'two' }
- validate_hash($foo, $bar)
- ENDofPUPPETcode
- scope.compiler.compile
+ describe 'valid inputs' do
+ it { is_expected.to run.with_params({}) }
+ it { is_expected.to run.with_params({'key' => 'value'}) }
+ it { is_expected.to run.with_params({}, {'key' => 'value'}) }
+ it { is_expected.to run.with_params({'key1' => 'value1'}, {'key2' => 'value2'}) }
end
- it "should not compile when an undef variable is passed" do
- Puppet[:code] = <<-'ENDofPUPPETcode'
- $foo = undef
- validate_hash($foo)
- ENDofPUPPETcode
- expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a Hash/)
+ describe 'invalid inputs' do
+ it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError, /is not a Hash/) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /is not a Hash/) }
+ it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /is not a Hash/) }
+ it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /is not a Hash/) }
+ it { is_expected.to run.with_params({}, []).and_raise_error(Puppet::ParseError, /is not a Hash/) }
+ it { is_expected.to run.with_params({}, 1).and_raise_error(Puppet::ParseError, /is not a Hash/) }
+ it { is_expected.to run.with_params({}, true).and_raise_error(Puppet::ParseError, /is not a Hash/) }
+ it { is_expected.to run.with_params({}, 'one').and_raise_error(Puppet::ParseError, /is not a Hash/) }
end
-
end
-
end
diff --git a/spec/functions/validate_integer_spec.rb b/spec/functions/validate_integer_spec.rb
new file mode 100755
index 0000000..6558d00
--- /dev/null
+++ b/spec/functions/validate_integer_spec.rb
@@ -0,0 +1,101 @@
+require 'spec_helper'
+
+describe 'validate_integer' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
+
+ # Checking for deprecation warning
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params(3)
+ end
+
+ describe 'signature validation' 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(1, 2, 3, 4).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+ [ true, 'true', false, 'false', 'iAmAString', '1test', '1 test', 'test 1', 'test 1 test', 7.0, -7.0, {}, { 'key' => 'value' }, { 1=> 2 }, '', :undef , 'x'].each do |invalid|
+ it { is_expected.to run.with_params(invalid).and_raise_error(Puppet::ParseError, /to be an Integer/) }
+ it { is_expected.to run.with_params(invalid, 10).and_raise_error(Puppet::ParseError, /to be an Integer/) }
+ it { is_expected.to run.with_params(invalid, 10, -10).and_raise_error(Puppet::ParseError, /to be an Integer/) }
+ it { is_expected.to run.with_params([0, 1, 2, invalid, 3, 4], 10, -10).and_raise_error(Puppet::ParseError, /to be an Integer/) }
+ end
+
+ context 'when running on modern rubies', :unless => RUBY_VERSION == '1.8.7' do
+ it { is_expected.to run.with_params([0, 1, 2, {1=>2}, 3, 4], 10, -10).and_raise_error(Puppet::ParseError, /to be an Integer/) }
+ end
+
+ context 'when running on ruby, which munges hashes weirdly', :if => RUBY_VERSION == '1.8.7' do
+ it { is_expected.to run.with_params([0, 1, 2, {1=>2}, 3, 4], 10, -10).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([0, 1, 2, {0=>2}, 3, 4], 10, -10).and_raise_error(Puppet::ParseError) }
+ end
+
+ it { is_expected.to run.with_params(1, '').and_raise_error(Puppet::ParseError, /to be unset or an Integer/) }
+ it { is_expected.to run.with_params(1, 2, '').and_raise_error(Puppet::ParseError, /to be unset or an Integer/) }
+ it { is_expected.to run.with_params(1, 2, 3).and_raise_error(Puppet::ParseError, /second argument to be larger than third argument/) }
+ end
+
+ context 'with no range constraints' do
+ it { is_expected.to run.with_params(1) }
+ it { is_expected.to run.with_params(-1) }
+ it { is_expected.to run.with_params('1') }
+ it { is_expected.to run.with_params('-1') }
+ it { is_expected.to run.with_params([1, 2, 3, 4]) }
+ it { is_expected.to run.with_params([1, '2', '3', 4]) }
+ end
+
+ context "with a maximum limit of 10" do
+ describe 'rejects numbers greater than the limit' do
+ it { is_expected.to run.with_params(11, 10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ it { is_expected.to run.with_params(100, 10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ it { is_expected.to run.with_params(2**65, 10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ it { is_expected.to run.with_params([1,2,10,100], 10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ end
+
+ describe 'accepts numbers less or equal to the limit' do
+ it { is_expected.to run.with_params(10, 10) }
+ it { is_expected.to run.with_params(1, 10) }
+ it { is_expected.to run.with_params(-1, 10) }
+ it { is_expected.to run.with_params('1', 10) }
+ it { is_expected.to run.with_params('-1', 10) }
+ it { is_expected.to run.with_params([1, 2, 3, 4], 10) }
+ it { is_expected.to run.with_params([1, '2', '3', 4], 10) }
+ end
+
+ context "with a minimum limit of -10" do
+ describe 'rejects numbers greater than the upper limit' do
+ it { is_expected.to run.with_params(11, 10, -10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ it { is_expected.to run.with_params(100, 10, -10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ it { is_expected.to run.with_params(2**65, 10, -10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ it { is_expected.to run.with_params([1,2,10,100], 10, -10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ end
+
+ describe 'rejects numbers smaller than the lower limit' do
+ it { is_expected.to run.with_params(-11, 10, -10).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+ it { is_expected.to run.with_params(-100, 10, -10).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+ it { is_expected.to run.with_params(-2**65, 10, -10).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+ it { is_expected.to run.with_params([-10, 1,2,10,-100], 10, -10).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+ end
+
+ describe 'accepts numbers between and including the limits' do
+ it { is_expected.to run.with_params(10, 10, -10) }
+ it { is_expected.to run.with_params(-10, 10, -10) }
+ it { is_expected.to run.with_params(1, 10, -10) }
+ it { is_expected.to run.with_params(-1, 10, -10) }
+ it { is_expected.to run.with_params('1', 10, -10) }
+ it { is_expected.to run.with_params('-1', 10, -10) }
+ it { is_expected.to run.with_params([1, 2, 3, 4], 10, -10) }
+ it { is_expected.to run.with_params([1, '2', '3', 4], 10, -10) }
+ end
+ end
+ end
+
+ it { is_expected.to run.with_params(10, 10, 10) }
+
+ describe 'empty upper limit is interpreted as infinity' do
+ it { is_expected.to run.with_params(11, '', 10) }
+ end
+end
diff --git a/spec/functions/validate_ip_address_spec.rb b/spec/functions/validate_ip_address_spec.rb
new file mode 100644
index 0000000..0414f5e
--- /dev/null
+++ b/spec/functions/validate_ip_address_spec.rb
@@ -0,0 +1,65 @@
+require 'spec_helper'
+
+describe 'validate_ip_address' do
+
+ describe 'signature validation' 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) }
+ end
+
+ describe 'valid inputs' do
+ it { is_expected.to run.with_params('0.0.0.0') }
+ it { is_expected.to run.with_params('8.8.8.8') }
+ it { is_expected.to run.with_params('127.0.0.1') }
+ it { is_expected.to run.with_params('10.10.10.10') }
+ it { is_expected.to run.with_params('194.232.104.150') }
+ it { is_expected.to run.with_params('244.24.24.24') }
+ it { is_expected.to run.with_params('255.255.255.255') }
+ it { is_expected.to run.with_params('1.2.3.4', '5.6.7.8') }
+ it { is_expected.to run.with_params('3ffe:0505:0002::') }
+ it { is_expected.to run.with_params('3ffe:0505:0002::', '3ffe:0505:0002::2') }
+ it { is_expected.to run.with_params('::1/64') }
+ it { is_expected.to run.with_params('fe80::a00:27ff:fe94:44d6/64') }
+
+ context 'Checking for deprecation warning', if: Puppet.version.to_f < 4.0 do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
+ # Checking for deprecation warning, which should only be provoked when the env variable for it is set.
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params('1.2.3.4')
+ end
+ it 'should display no warning for deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "false"
+ scope.expects(:warning).with(includes('This method is deprecated')).never
+ is_expected.to run.with_params('1.2.3.4')
+ end
+ end
+
+ context 'with netmasks' do
+ it { is_expected.to run.with_params('8.8.8.8/0') }
+ it { is_expected.to run.with_params('8.8.8.8/16') }
+ it { is_expected.to run.with_params('8.8.8.8/32') }
+ it { is_expected.to run.with_params('8.8.8.8/255.255.0.0') }
+ end
+ end
+
+ describe 'invalid inputs' do
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /is not a valid IP/) }
+ it { is_expected.to run.with_params('0.0.0').and_raise_error(Puppet::ParseError, /is not a valid IP/) }
+ it { is_expected.to run.with_params('0.0.0.256').and_raise_error(Puppet::ParseError, /is not a valid IP/) }
+ it { is_expected.to run.with_params('0.0.0.0.0').and_raise_error(Puppet::ParseError, /is not a valid IP/) }
+ it { is_expected.to run.with_params('1.2.3.4', {}).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('1.2.3.4', 1).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('1.2.3.4', true).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('1.2.3.4', 'one').and_raise_error(Puppet::ParseError, /is not a valid IP/) }
+ it { is_expected.to run.with_params('::1', {}).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('::1', true).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('::1', 'one').and_raise_error(Puppet::ParseError, /is not a valid IP/) }
+ end
+end
diff --git a/spec/functions/validate_ipv4_address_spec.rb b/spec/functions/validate_ipv4_address_spec.rb
index 45401a4..6e4ca05 100755
--- a/spec/functions/validate_ipv4_address_spec.rb
+++ b/spec/functions/validate_ipv4_address_spec.rb
@@ -1,64 +1,41 @@
-#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
-require "spec_helper"
+describe 'validate_ipv4_address' do
-describe Puppet::Parser::Functions.function(:validate_ipv4_address) do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- describe "when calling validate_ipv4_address from puppet" do
- describe "when given IPv4 address strings" do
- it "should compile with one argument" do
- Puppet[:code] = "validate_ipv4_address('1.2.3.4')"
- scope.compiler.compile
- end
+ describe 'signature validation' 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) }
+ end
- it "should compile with multiple arguments" do
- Puppet[:code] = "validate_ipv4_address('1.2.3.4', '5.6.7.8')"
- scope.compiler.compile
- end
+ context 'Checking for deprecation warning', if: Puppet.version.to_f < 4.0 do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
end
-
- describe "when given an IPv6 address" do
- it "should not compile" do
- Puppet[:code] = "validate_ipv4_address('3ffe:505')"
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /not a valid IPv4 address/)
- end
+ # Checking for deprecation warning, which should only be provoked when the env variable for it is set.
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params(SharedData::IPV4_PATTERNS.first)
end
-
- describe "when given other strings" do
- it "should not compile" do
- Puppet[:code] = "validate_ipv4_address('hello', 'world')"
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /not a valid IPv4 address/)
- end
+ it 'should display no warning for deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "false"
+ scope.expects(:warning).with(includes('This method is deprecated')).never
+ is_expected.to run.with_params(SharedData::IPV4_PATTERNS.first)
end
+ end
- describe "when given numbers" do
- it "should not compile" do
- Puppet[:code] = "validate_ipv4_address(1, 2)"
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /is not a valid IPv4 address/)
- end
- end
+ SharedData::IPV4_PATTERNS.each do |value|
+ it { is_expected.to run.with_params(value) }
+ end
- describe "when given booleans" do
- it "should not compile" do
- Puppet[:code] = "validate_ipv4_address(true, false)"
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /is not a string/)
- end
- end
+ SharedData::IPV4_NEGATIVE_PATTERNS.each do |value|
+ it { is_expected.to run.with_params(value).and_raise_error(Puppet::ParseError, /is not a valid IPv4/) }
+ end
- it "should not compile when no arguments are passed" do
- Puppet[:code] = "validate_ipv4_address()"
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /wrong number of arguments/)
+ describe 'invalid inputs' do
+ [ {}, [], 1, true ].each do |invalid|
+ it { is_expected.to run.with_params(invalid).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params(SharedData::IPV4_PATTERNS.first, invalid).and_raise_error(Puppet::ParseError, /is not a string/) }
end
end
end
diff --git a/spec/functions/validate_ipv6_address_spec.rb b/spec/functions/validate_ipv6_address_spec.rb
index a839d90..78810d4 100755
--- a/spec/functions/validate_ipv6_address_spec.rb
+++ b/spec/functions/validate_ipv6_address_spec.rb
@@ -1,67 +1,50 @@
-#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
-require "spec_helper"
-
-describe Puppet::Parser::Functions.function(:validate_ipv6_address) do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- describe "when calling validate_ipv6_address from puppet" do
- describe "when given IPv6 address strings" do
- it "should compile with one argument" do
- Puppet[:code] = "validate_ipv6_address('3ffe:0505:0002::')"
- scope.compiler.compile
- end
+describe 'validate_ipv6_address' do
+
+ describe 'signature validation' 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) }
+ end
- it "should compile with multiple arguments" do
- Puppet[:code] = "validate_ipv6_address('3ffe:0505:0002::', '3ffe:0505:0001::')"
- scope.compiler.compile
- end
+ context 'Checking for deprecation warning', if: Puppet.version.to_f < 4.0 do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
end
-
- describe "when given an ipv4 address" do
- it "should not compile" do
- Puppet[:code] = "validate_ipv6_address('1.2.3.4')"
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /not a valid IPv6 address/)
- end
+ # Checking for deprecation warning, which should only be provoked when the env variable for it is set.
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params('3ffe:0505:0002::')
end
-
- describe "when given other strings" do
- it "should not compile" do
- Puppet[:code] = "validate_ipv6_address('hello', 'world')"
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /not a valid IPv6 address/)
- end
+ it 'should display no warning for deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "false"
+ scope.expects(:warning).with(includes('This method is deprecated')).never
+ is_expected.to run.with_params('3ffe:0505:0002::')
end
+ end
- # 1.8.7 is EOL'd and also absolutely insane about ipv6
- unless RUBY_VERSION == '1.8.7'
- describe "when given numbers" do
- it "should not compile" do
- Puppet[:code] = "validate_ipv6_address(1, 2)"
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /not a valid IPv6 address/)
- end
- end
- end
-
- describe "when given booleans" do
- it "should not compile" do
- Puppet[:code] = "validate_ipv6_address(true, false)"
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /is not a string/)
- end
- end
+ describe 'valid inputs' do
+ it { is_expected.to run.with_params('3ffe:0505:0002::') }
+ it { is_expected.to run.with_params('3ffe:0505:0002::', '3ffe:0505:0002::2') }
+ it { is_expected.to run.with_params('::1/64') }
+ it { is_expected.to run.with_params('fe80::a00:27ff:fe94:44d6/64') }
+ end
- it "should not compile when no arguments are passed" do
- Puppet[:code] = "validate_ipv6_address()"
- expect {
- scope.compiler.compile
- }.to raise_error(Puppet::ParseError, /wrong number of arguments/)
+ describe 'invalid inputs' do
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /is not a valid IPv6/) }
+ it { is_expected.to run.with_params('0.0.0').and_raise_error(Puppet::ParseError, /is not a valid IPv6/) }
+ it { is_expected.to run.with_params('0.0.0.256').and_raise_error(Puppet::ParseError, /is not a valid IPv6/) }
+ it { is_expected.to run.with_params('0.0.0.0.0').and_raise_error(Puppet::ParseError, /is not a valid IPv6/) }
+ it { is_expected.to run.with_params('affe:beef').and_raise_error(Puppet::ParseError, /is not a valid IPv6/) }
+ it { is_expected.to run.with_params('::1', {}).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('::1', true).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('::1', 'one').and_raise_error(Puppet::ParseError, /is not a valid IPv6/) }
+ context 'unless running on ruby 1.8.7', :if => RUBY_VERSION != '1.8.7' do
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params('::1', 1).and_raise_error(Puppet::ParseError, /is not a string/) }
end
end
end
diff --git a/spec/functions/validate_legacy_spec.rb b/spec/functions/validate_legacy_spec.rb
new file mode 100644
index 0000000..50cb317
--- /dev/null
+++ b/spec/functions/validate_legacy_spec.rb
@@ -0,0 +1,68 @@
+require 'spec_helper'
+
+if Puppet.version.to_f >= 4.0
+ describe 'validate_legacy' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params.and_raise_error(ArgumentError) }
+
+ describe 'when passing the type assertion and passing the previous validation' do
+ before do
+ scope.expects(:function_validate_foo).with([5]).once
+ Puppet.expects(:notice).never
+ end
+ it 'passes without notice' do
+ is_expected.to run.with_params('Integer', 'validate_foo', 5)
+ end
+ end
+
+ describe 'when passing the type assertion and failing the previous validation' do
+ before do
+ scope.expects(:function_validate_foo).with([5]).raises(Puppet::ParseError, 'foo').once
+ Puppet.expects(:notice).with(includes('Accepting previously invalid value for target type'))
+ end
+ it 'passes with a notice about newly accepted value' do
+ is_expected.to run.with_params('Integer', 'validate_foo', 5)
+ end
+ end
+
+ describe 'when failing the type assertion and passing the previous validation' do
+ before do
+ scope.expects(:function_validate_foo).with(['5']).once
+ subject.func.expects(:call_function).with('deprecation', 'validate_legacy', includes('Integer')).once
+ end
+ it 'passes with a deprecation message' do
+ is_expected.to run.with_params('Integer', 'validate_foo', '5')
+ end
+ end
+
+ describe 'when failing the type assertion and failing the previous validation' do
+ before do
+ scope.expects(:function_validate_foo).with(['5']).raises(Puppet::ParseError, 'foo').once
+ subject.func.expects(:call_function).with('fail', includes('Integer')).once
+ end
+ it 'fails with a helpful message' do
+ is_expected.to run.with_params('Integer', 'validate_foo', '5')
+ end
+ end
+
+ describe 'when passing in undef' do
+ before do
+ scope.expects(:function_validate_foo).with([:undef]).once
+ Puppet.expects(:notice).never
+ end
+ it 'works' do
+ is_expected.to run.with_params('Optional[Integer]', 'validate_foo', :undef)
+ end
+ end
+
+ describe 'when passing in multiple arguments' do
+ before do
+ scope.expects(:function_validate_foo).with([:undef, 1, 'foo']).once
+ Puppet.expects(:notice).never
+ end
+ it 'passes with a deprecation message' do
+ is_expected.to run.with_params('Optional[Integer]', 'validate_foo', :undef, 1, 'foo')
+ end
+ end
+ end
+end
diff --git a/spec/functions/validate_numeric_spec.rb b/spec/functions/validate_numeric_spec.rb
new file mode 100755
index 0000000..4c0e24d
--- /dev/null
+++ b/spec/functions/validate_numeric_spec.rb
@@ -0,0 +1,100 @@
+require 'spec_helper'
+
+describe 'validate_numeric' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
+
+ # Checking for deprecation warning
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params(3)
+ end
+
+ describe 'signature validation' 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(1, 2, 3, 4).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+ [ true, 'true', false, 'false', 'iAmAString', '1test', '1 test', 'test 1', 'test 1 test', {}, { 'key' => 'value' }, { 1=> 2 }, '', :undef , 'x'].each do |invalid|
+ it { is_expected.to run.with_params(invalid).and_raise_error(Puppet::ParseError, /to be a Numeric/) }
+ it { is_expected.to run.with_params(invalid, 10.0).and_raise_error(Puppet::ParseError, /to be a Numeric/) }
+ it { is_expected.to run.with_params(invalid, 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be a Numeric/) }
+ end
+
+ context 'when running on modern rubies', :unless => RUBY_VERSION == '1.8.7' do
+ it { is_expected.to run.with_params([0, 1, 2, {1=>2}, 3, 4], 10, -10).and_raise_error(Puppet::ParseError, /to be a Numeric/) }
+ end
+
+ context 'when running on ruby, which munges hashes weirdly', :if => RUBY_VERSION == '1.8.7' do
+ it { is_expected.to run.with_params([0, 1, 2, {1=>2}, 3, 4], 10, -10).and_raise_error(Puppet::ParseError) }
+ it { is_expected.to run.with_params([0, 1, 2, {0=>2}, 3, 4], 10, -10).and_raise_error(Puppet::ParseError) }
+ end
+
+ it { is_expected.to run.with_params(1, '').and_raise_error(Puppet::ParseError, /to be unset or a Numeric/) }
+ it { is_expected.to run.with_params(1, 2, '').and_raise_error(Puppet::ParseError, /to be unset or a Numeric/) }
+ it { is_expected.to run.with_params(1, 2, 3).and_raise_error(Puppet::ParseError, /second argument to be larger than third argument/) }
+ end
+
+ context 'with no range constraints' do
+ it { is_expected.to run.with_params(1) }
+ it { is_expected.to run.with_params(-1) }
+ it { is_expected.to run.with_params('1') }
+ it { is_expected.to run.with_params('-1') }
+ it { is_expected.to run.with_params([1, 2, 3, 4]) }
+ it { is_expected.to run.with_params([1, '2', '3', 4]) }
+ end
+
+ context "with a maximum limit of 10.0" do
+ describe 'rejects numbers greater than the limit' do
+ it { is_expected.to run.with_params(11, 10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ it { is_expected.to run.with_params(100, 10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ it { is_expected.to run.with_params(2**65, 10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ it { is_expected.to run.with_params([1,2,10.0,100], 10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ end
+
+ describe 'accepts numbers less or equal to the limit' do
+ it { is_expected.to run.with_params(10.0, 10.0) }
+ it { is_expected.to run.with_params(1, 10.0) }
+ it { is_expected.to run.with_params(-1, 10.0) }
+ it { is_expected.to run.with_params('1', 10.0) }
+ it { is_expected.to run.with_params('-1', 10.0) }
+ it { is_expected.to run.with_params([1, 2, 3, 4], 10.0) }
+ it { is_expected.to run.with_params([1, '2', '3', 4], 10.0) }
+ end
+
+ context "with a minimum limit of -10.0" do
+ describe 'rejects numbers greater than the upper limit' do
+ it { is_expected.to run.with_params(11, 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ it { is_expected.to run.with_params(100, 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ it { is_expected.to run.with_params(2**65, 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ it { is_expected.to run.with_params([1,2,10.0,100], 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+ end
+
+ describe 'rejects numbers smaller than the lower limit' do
+ it { is_expected.to run.with_params(-11, 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+ it { is_expected.to run.with_params(-100, 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+ it { is_expected.to run.with_params(-2**65, 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+ it { is_expected.to run.with_params([-10.0, 1,2,10.0,-100], 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+ end
+
+ describe 'accepts numbers between and including the limits' do
+ it { is_expected.to run.with_params(10.0, 10.0, -10.0) }
+ it { is_expected.to run.with_params(-10.0, 10.0, -10.0) }
+ it { is_expected.to run.with_params(1, 10.0, -10.0) }
+ it { is_expected.to run.with_params(-1, 10.0, -10.0) }
+ it { is_expected.to run.with_params('1', 10.0, -10.0) }
+ it { is_expected.to run.with_params('-1', 10.0, -10.0) }
+ it { is_expected.to run.with_params([1, 2, 3, 4], 10.0, -10.0) }
+ it { is_expected.to run.with_params([1, '2', '3', 4], 10.0, -10.0) }
+ end
+ end
+ end
+
+ it { is_expected.to run.with_params(10.0, 10.0, 10.0) }
+
+ describe 'empty upper limit is interpreted as infinity' do
+ it { is_expected.to run.with_params(11, '', 10.0) }
+ end
+end
diff --git a/spec/functions/validate_re_spec.rb b/spec/functions/validate_re_spec.rb
index d29988b..3531182 100755
--- a/spec/functions/validate_re_spec.rb
+++ b/spec/functions/validate_re_spec.rb
@@ -1,75 +1,54 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:validate_re) do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- # The subject of these examplres is the method itself.
- subject do
- # This makes sure the function is loaded within each test
- function_name = Puppet::Parser::Functions.function(:validate_re)
- scope.method(function_name)
+describe 'validate_re' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
end
- context 'Using Puppet::Parser::Scope.new' do
-
- describe 'Garbage inputs' do
- inputs = [
- [ nil ],
- [ [ nil ] ],
- [ { 'foo' => 'bar' } ],
- [ { } ],
- [ '' ],
- [ "one", "one", "MSG to User", "4th arg" ],
- ]
-
- inputs.each do |input|
- it "validate_re(#{input.inspect}) should fail" do
- expect { subject.call [input] }.to raise_error Puppet::ParseError
- end
- end
- end
-
- describe 'Valid inputs' do
- inputs = [
- [ '/full/path/to/something', '^/full' ],
- [ '/full/path/to/something', 'full' ],
- [ '/full/path/to/something', ['full', 'absent'] ],
- [ '/full/path/to/something', ['full', 'absent'], 'Message to the user' ],
- ]
-
- inputs.each do |input|
- it "validate_re(#{input.inspect}) should not fail" do
- expect { subject.call input }.not_to raise_error
- end
- end
- end
- describe "Valid inputs which should raise an exception without a message" do
- # The intent here is to make sure valid inputs raise exceptions when they
- # don't specify an error message to display. This is the behvior in
- # 2.2.x and prior.
- inputs = [
- [ "hello", [ "bye", "later", "adios" ] ],
- [ "greetings", "salutations" ],
- ]
+ # Checking for deprecation warning
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params('', '')
+ end
- inputs.each do |input|
- it "validate_re(#{input.inspect}) should fail" do
- expect { subject.call input }.to raise_error /validate_re.*?does not match/
- end
- end
+ describe 'signature validation' 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('', '', '', 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+ describe 'valid inputs' do
+ it { is_expected.to run.with_params('', '') }
+ it { is_expected.to run.with_params('', ['']) }
+ it { is_expected.to run.with_params('', [''], 'custom error') }
+ it { is_expected.to run.with_params('one', '^one') }
+ it { is_expected.to run.with_params('one', [ '^one', '^two' ]) }
+ it { is_expected.to run.with_params('one', [ '^one', '^two' ], 'custom error') }
end
- describe "Nicer Error Messages" do
- # The intent here is to make sure the function returns the 3rd argument
- # in the exception thrown
- inputs = [
- [ "hello", [ "bye", "later", "adios" ], "MSG to User" ],
- [ "greetings", "salutations", "Error, greetings does not match salutations" ],
- ]
- inputs.each do |input|
- it "validate_re(#{input.inspect}) should fail" do
- expect { subject.call input }.to raise_error /#{input[2]}/
+ describe 'invalid inputs' do
+ it { is_expected.to run.with_params('', []).and_raise_error(Puppet::ParseError, /does not match/) }
+ it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError, /does not match/) }
+ it { is_expected.to run.with_params('', 'two').and_raise_error(Puppet::ParseError, /does not match/) }
+ it { is_expected.to run.with_params('', ['two']).and_raise_error(Puppet::ParseError, /does not match/) }
+ it { is_expected.to run.with_params('', ['two'], 'custom error').and_raise_error(Puppet::ParseError, /custom error/) }
+ it { is_expected.to run.with_params('notone', '^one').and_raise_error(Puppet::ParseError, /does not match/) }
+ it { is_expected.to run.with_params('notone', [ '^one', '^two' ]).and_raise_error(Puppet::ParseError, /does not match/) }
+ it { is_expected.to run.with_params('notone', [ '^one', '^two' ], 'custom error').and_raise_error(Puppet::ParseError, /custom error/) }
+
+ describe 'non-string inputs' do
+ [
+ 1, # Fixnum
+ 3.14, # Float
+ nil, # NilClass
+ true, # TrueClass
+ false, # FalseClass
+ ["10"], # Array
+ :key, # Symbol
+ {:key=>"val"}, # Hash
+ ].each do |input|
+ it { is_expected.to run.with_params(input, '.*').and_raise_error(Puppet::ParseError, /needs to be a String/) }
end
end
end
diff --git a/spec/functions/validate_slength_spec.rb b/spec/functions/validate_slength_spec.rb
index e23f61a..e4162de 100755
--- a/spec/functions/validate_slength_spec.rb
+++ b/spec/functions/validate_slength_spec.rb
@@ -1,67 +1,72 @@
-#! /usr/bin/env ruby -S rspec
-
require 'spec_helper'
-describe "the validate_slength function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("validate_slength")).to eq("function_validate_slength")
+describe 'validate_slength' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
end
- describe "validating the input argument types" do
- it "raises an error if there are less than two arguments" do
- expect { scope.function_validate_slength([]) }.to raise_error Puppet::ParseError, /Wrong number of arguments/
- end
-
- it "raises an error if there are more than three arguments" do
- expect { scope.function_validate_slength(['input', 1, 2, 3]) }.to raise_error Puppet::ParseError, /Wrong number of arguments/
- end
-
- it "raises an error if the first argument is not a string" do
- expect { scope.function_validate_slength([Object.new, 2, 1]) }.to raise_error Puppet::ParseError, /Expected first argument.*got .*Object/
- end
+ # Checking for deprecation warning
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params('1234567890', 10)
+ end
+
+ describe 'signature validation' 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('', 2, 3, 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ it { is_expected.to run.with_params('', '').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, /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 equal to or larger than third argument/) }
+ end
- it "raises an error if the second argument cannot be cast to an Integer" do
- expect { scope.function_validate_slength(['input', Object.new]) }.to raise_error Puppet::ParseError, /Expected second argument.*got .*Object/
+ context "with a maximum length of 10" do
+ describe 'rejects strings longer than the limit' do
+ it { is_expected.to run.with_params('1234567890a', 10).and_raise_error(Puppet::ParseError, /Expected length/) }
+ it { is_expected.to run.with_params('1234567890abcdef', 10).and_raise_error(Puppet::ParseError, /Expected length/) }
+ it { is_expected.to run.with_params([ 'one', '1234567890abcdef' ], 10).and_raise_error(Puppet::ParseError, /Expected length/) }
end
- it "raises an error if the third argument cannot be cast to an Integer" do
- expect { scope.function_validate_slength(['input', 1, Object.new]) }.to raise_error Puppet::ParseError, /Expected third argument.*got .*Object/
+ describe 'accepts strings shorter or equal to the limit' do
+ it { is_expected.to run.with_params('1234567890', 10) }
+ it { is_expected.to run.with_params('12345', 10) }
+ it { is_expected.to run.with_params([ 'one', 'two' ], 10) }
end
- it "raises an error if the second argument is smaller than the third argument" do
- expect { scope.function_validate_slength(['input', 1, 2]) }.to raise_error Puppet::ParseError, /Expected second argument to be larger than third argument/
- end
- end
-
- describe "validating the input string length" do
- describe "when the input is a string" do
- it "fails validation if the string is larger than the max length" do
- expect { scope.function_validate_slength(['input', 1]) }.to raise_error Puppet::ParseError, /Expected length .* between 0 and 1, was 5/
- end
-
- it "fails validation if the string is less than the min length" do
- expect { scope.function_validate_slength(['input', 10, 6]) }.to raise_error Puppet::ParseError, /Expected length .* between 6 and 10, was 5/
- end
-
- it "doesn't raise an error if the string is under the max length" do
- scope.function_validate_slength(['input', 10])
+ context "with a minimum length of 5" do
+ describe 'rejects strings longer than the upper limit' do
+ it { is_expected.to run.with_params('1234567890a', 10, 5).and_raise_error(Puppet::ParseError, /Expected length/) }
+ it { is_expected.to run.with_params('1234567890abcdef', 10, 5).and_raise_error(Puppet::ParseError, /Expected length/) }
end
- it "doesn't raise an error if the string is equal to the max length" do
- scope.function_validate_slength(['input', 5])
+ describe 'rejects numbers shorter than the lower limit' do
+ it { is_expected.to run.with_params('one', 10, 5).and_raise_error(Puppet::ParseError, /Expected length/) }
+ it { is_expected.to run.with_params(['12345678', 'two'], 10, 5).and_raise_error(Puppet::ParseError, /Expected length/) }
end
- it "doesn't raise an error if the string is equal to the min length" do
- scope.function_validate_slength(['input', 10, 5])
+ describe 'accepts strings of length between and including the limits' do
+ it { is_expected.to run.with_params('12345', 10, 5) }
+ it { is_expected.to run.with_params('123456', 10, 5) }
+ it { is_expected.to run.with_params('1234567', 10, 5) }
+ it { is_expected.to run.with_params('12345678', 10, 5) }
+ it { is_expected.to run.with_params('123456789', 10, 5) }
+ it { is_expected.to run.with_params('1234567890', 10, 5) }
+ it { is_expected.to run.with_params(['1233456', '12345678'], 10, 5) }
end
end
+ end
- describe "when the input is an array" do
- it "fails validation if one of the array elements is not a string" do
- expect { scope.function_validate_slength([["a", "b", Object.new], 2]) }.to raise_error Puppet::ParseError, /Expected element at array position 2 .*String, got .*Object/
- end
- end
+ describe 'corner cases' do
+ it { pending('this should work'); is_expected.to run.with_params('', 0, 0) }
+ it { is_expected.to run.with_params('1234567890', 10, 10) }
+ end
+
+ describe 'empty upper limit is interpreted as infinity' do
+ it { pending('not implemented'); is_expected.to run.with_params('1234567890ab', '', 10) }
+ it { pending('not implemented'); is_expected.to run.with_params('12345678', '', 10).and_raise_error(Puppet::ParseError, /Expected length/) }
end
end
diff --git a/spec/functions/validate_string_spec.rb b/spec/functions/validate_string_spec.rb
index 3b4fb3e..0907ede 100755
--- a/spec/functions/validate_string_spec.rb
+++ b/spec/functions/validate_string_spec.rb
@@ -1,60 +1,33 @@
-#! /usr/bin/env ruby -S rspec
-
require 'spec_helper'
-describe Puppet::Parser::Functions.function(:validate_string) do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- describe 'when calling validate_string from puppet' do
-
- %w{ foo bar baz }.each do |the_string|
-
- it "should compile when #{the_string} is a string" do
- Puppet[:code] = "validate_string('#{the_string}')"
- scope.compiler.compile
- end
-
- it "should compile when #{the_string} is a bare word" do
- Puppet[:code] = "validate_string(#{the_string})"
- scope.compiler.compile
- end
-
- end
-
- %w{ true false }.each do |the_string|
- it "should compile when #{the_string} is a string" do
- Puppet[:code] = "validate_string('#{the_string}')"
- scope.compiler.compile
- end
-
- it "should not compile when #{the_string} is a bare word" do
- Puppet[:code] = "validate_string(#{the_string})"
- expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a string/)
- end
- end
+describe 'validate_string' do
+ after(:all) do
+ ENV.delete('STDLIB_LOG_DEPRECATIONS')
+ end
+
+ # Checking for deprecation warning
+ it 'should display a single deprecation' do
+ ENV['STDLIB_LOG_DEPRECATIONS'] = "true"
+ scope.expects(:warning).with(includes('This method is deprecated'))
+ is_expected.to run.with_params('', '')
+ end
- it "should compile when multiple string arguments are passed" do
- Puppet[:code] = <<-'ENDofPUPPETcode'
- $foo = ''
- $bar = 'two'
- validate_string($foo, $bar)
- ENDofPUPPETcode
- scope.compiler.compile
- end
+ describe 'signature validation' 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 "should compile when an explicitly undef variable is passed (NOTE THIS MAY NOT BE DESIRABLE)" do
- Puppet[:code] = <<-'ENDofPUPPETcode'
- $foo = undef
- validate_string($foo)
- ENDofPUPPETcode
- scope.compiler.compile
+ describe 'valid inputs' do
+ it { is_expected.to run.with_params('') }
+ it { is_expected.to run.with_params(nil) }
+ it { is_expected.to run.with_params('one') }
+ it { is_expected.to run.with_params('one', 'two') }
end
- it "should compile when an undefined variable is passed (NOTE THIS MAY NOT BE DESIRABLE)" do
- Puppet[:code] = <<-'ENDofPUPPETcode'
- validate_string($foobarbazishouldnotexist)
- ENDofPUPPETcode
- scope.compiler.compile
+ describe 'invalid inputs' do
+ it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /is not a string/) }
end
end
end
diff --git a/spec/functions/validate_x509_rsa_key_pair_spec.rb b/spec/functions/validate_x509_rsa_key_pair_spec.rb
new file mode 100755
index 0000000..eb63310
--- /dev/null
+++ b/spec/functions/validate_x509_rsa_key_pair_spec.rb
@@ -0,0 +1,180 @@
+require 'spec_helper'
+
+describe 'validate_x509_rsa_key_pair' do
+
+ let(:valid_cert) do
+ <<EOS
+-----BEGIN CERTIFICATE-----
+MIIC9jCCAeCgAwIBAgIRAK11n3X7aypJ7FPM8UFyAeowCwYJKoZIhvcNAQELMBIx
+EDAOBgNVBAoTB0FjbWUgQ28wHhcNMTUxMTIzMjIzOTU4WhcNMTYxMTIyMjIzOTU4
+WjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAz9bY/piKahD10AiJSfbI2A8NG5UwRz0r9T/WfvNVdhgrsGFgNQjvpUoZ
+nNJpQIHBbgMOiXqfATFjJl5FjEkSf7GUHohlGVls9MX2JmVvknzsiitd75H/EJd+
+N+k915lix8Vqmj8d1CTlbF/8tEjzANI67Vqw5QTuqebO7rkIUvRg6yiRfSo75FK1
+RinCJyl++kmleBwQZBInQyg95GvJ5JTqMzBs67DeeyzskDhTeTePRYVF2NwL8QzY
+htvLIBERTNsyU5i7nkxY5ptUwgFUwd93LH4Q19tPqL5C5RZqXxhE51thOOwafm+a
+W/cRkqYqV+tv+j1jJ3WICyF1JNW0BQIDAQABo0swSTAOBgNVHQ8BAf8EBAMCAKAw
+EwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAUBgNVHREEDTALggls
+b2NhbGhvc3QwCwYJKoZIhvcNAQELA4IBAQAzRo0hpVTrFQZLIXpwvKwZVGvJdCkV
+P95DTsSk/VTGV+/YtxrRqks++hJZnctm2PbnTsCAoIP3AMx+vicCKiKrxvpsLU8/
++6cowUbcuGMdSQktwDqbAgEhQlLsETll06w1D/KC+ejOc4+LRn3GQcEyGDtMk/EX
+IeAvBZHr4/kVXWnfo6kzCLcku1f8yE/yDEFClZe9XV1Lk/s+3YfXVtNnMJJ1giZI
+QVOe6CkmuQq+4AtIeW8aLkvlfp632jag1F77a1y+L268koKkj0hBMrtcErVQaxmq
+xym0+soR4Tk4pTIGckeFglrLxkP2JpM/yTwSEAVlmG9vgTliYKyR0uMl
+-----END CERTIFICATE-----
+EOS
+ end
+
+ let(:valid_key) do
+ <<EOS
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAz9bY/piKahD10AiJSfbI2A8NG5UwRz0r9T/WfvNVdhgrsGFg
+NQjvpUoZnNJpQIHBbgMOiXqfATFjJl5FjEkSf7GUHohlGVls9MX2JmVvknzsiitd
+75H/EJd+N+k915lix8Vqmj8d1CTlbF/8tEjzANI67Vqw5QTuqebO7rkIUvRg6yiR
+fSo75FK1RinCJyl++kmleBwQZBInQyg95GvJ5JTqMzBs67DeeyzskDhTeTePRYVF
+2NwL8QzYhtvLIBERTNsyU5i7nkxY5ptUwgFUwd93LH4Q19tPqL5C5RZqXxhE51th
+OOwafm+aW/cRkqYqV+tv+j1jJ3WICyF1JNW0BQIDAQABAoIBADAiZ/r+xP+vkd5u
+O61/lCBFzBlZQecdybJw6HJaVK6XBndA9hESUr4LHUdui6W+51ddKd65IV4bXAUk
+zCKjQb+FFvLDT/bA+TTvLATUdTSN7hJJ3OWBAHuNOlQklof6JCB0Hi4+89+P8/pX
+eKUgR/cmuTMDT/iaXdPHeqFbBQyA1ZpQFRjN5LyyJMS/9FkywuNc5wlpsArtc51T
+gIKENUZCuPhosR+kMFc2iuTNvqZWPhvouSrmhi2O6nSqV+oy0+irlqSpCF2GsCI8
+72TtLpq94Grrq0BEH5avouV+Lp4k83vO65OKCQKUFQlxz3Xkxm2U3J7KzxqnRtM3
+/b+cJ/kCgYEA6/yOnaEYhH/7ijhZbPn8RujXZ5VGJXKJqIuaPiHMmHVS5p1j6Bah
+2PcnqJA2IlLs3UloN+ziAxAIH6KCBiwlQ/uPBNMMaJsIjPNBEy8axjndKhKUpidg
+R0OJ7RQqMShOJ8akrSfWdPtXC/GBuwCYE//t77GgZaIMO3FcT9EKA48CgYEA4Xcx
+Fia0Jg9iyAhNmUOXI6hWcGENavMx01+x7XFhbnMjIKTZevFfTnTkrX6HyLXyGtMU
+gHOn+k4PE/purI4ARrKO8m5wYEKqSIt4dBMTkIXXirfQjXgfjR8E4T/aPe5fOFZo
+7OYuxLRtzmG1C2sW4txwKAKX1LaWcVx/RLSttSsCgYBbcj8Brk+F6OJcqYFdzXGJ
+OOlf5mSMVlopyg83THmwCqbZXtw8L6kAHqZrl5airmfDSJLuOQlMDoZXW+3u3mSC
+d5TwVahVUN57YDgzaumBLyMZDqIz0MZqVy23hTzkV64Rk9R0lR9xrYQJyMhw4sYL
+2f0mCTsSpzz+O+t9so+i2QKBgEC38gMlwPhb2kMI/x1LZYr6uzUu5qcYf+jowy4h
+KZKGwkKQj0zXFEB1FV8nvtpCP+irRmtIx6L13SYi8LnfWPzyLE4ynVdES5TfVAgd
+obQOdzx+XwL8xDHCAaiWp5K3ZeXKB/xYZnxYPlzLdyh76Ond1OPnOqX4c16+6llS
+c7pZAoGATd9NckT0XtXLEsF3IraDivq8dP6bccX2DNfS8UeEvRRrRwpFpSRrmuGb
+jbG4yzoIX4RjQfj/z48hwhJB+cKiN9WwcPsFXtHe7v3F6BRwK0JUfrCiXad8/SGZ
+KAf7Dfqi608zBdnPWHacre2Y35gPHB00nFQOLS6u46aBNSq07YA=
+-----END RSA PRIVATE KEY-----
+EOS
+ end
+
+ let(:another_valid_key) do
+ <<EOS
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAoISxYJBTPAeAzFnm+lE/ljLlmGal2Xr3vwZKkvJiuKA/m4QJ
+0ZNdtkBSDOVuG2dXVv6W4sChRtsCdvuVe7bjTYvlU8TWM3VEJDL9l9cRXScxxlKQ
+Xwb35y1yV35NJfaK/jzm9KcErtQQs1RxvGlWRaohmLM8uQcuhjZfMsSlQoHQD5LX
+sbPtk82RPyxYc1dj2vsaoi1VvuP2+jv4xLQOmNJY1bT5GTurqiltmxEtWhNNmGg0
+2wtK00ifqLVO5HNc3gXQCDM2M99Sbmn1YtbrgsU9xMYfcPmvQvb+YoKskyoqck+c
+HR//hi7vslbxABrny15LBkEfRc4TickphSGYXwIDAQABAoIBAATEzGw8/WwMIQRx
+K06GeWgh7PZBHm4+m/ud2TtSXiJ0CE+7dXs3cJJIiOd/LW08/bhE6gCkjmYHfaRB
+Ryicv1X/cPmzIFX5BuQ4a5ZGOmrVDkKBE27vSxAgJoR46RvWnjx9XLMp/xaekDxz
+psldK8X4DvV1ZbltgDFWji947hvyqUtHdKnkQnc5j7aCIFJf9GMfzaeeDPMaL8WF
+mVL4iy9EAOjNOHBshZj/OHyU5FbJ8ROwZQlCOiLCdFegftSIXt8EYDnjB3BdsALH
+N6hquqrD7xDKyRbTD0K7lqxUubuMwTQpi61jZD8TBTXEPyFVAnoMpXkc0Y+np40A
+YiIsR+kCgYEAyrc4Bh6fb9gt49IXGXOSRZ5i5+TmJho4kzIONrJ7Ndclwx9wzHfh
+eGBodWaw5CxxQGMf4vEiaZrpAiSFeDffBLR+Wa2TFE5aWkdYkR34maDjO00m4PE1
+S+YsZoGw7rGmmj+KS4qv2T26FEHtUI+F31RC1FPohLsQ22Jbn1ORipsCgYEAyrYB
+J2Ncf2DlX1C0GfxyUHQOTNl0V5gpGvpbZ0WmWksumYz2kSGOAJkxuDKd9mKVlAcz
+czmN+OOetuHTNqds2JJKKJy6hJbgCdd9aho3dId5Xs4oh4YwuFQiG8R/bJZfTlXo
+99Qr02L7MmDWYLmrR3BA/93UPeorHPtjqSaYU40CgYEAtmGfWwokIglaSDVVqQVs
+3YwBqmcrla5TpkMLvLRZ2/fktqfL4Xod9iKu+Klajv9ZKTfFkXWno2HHL7FSD/Yc
+hWwqnV5oDIXuDnlQOse/SeERb+IbD5iUfePpoJQgbrCQlwiB0TNGwOojR2SFMczf
+Ai4aLlQLx5dSND9K9Y7HS+8CgYEAixlHQ2r4LuQjoTs0ytwi6TgqE+vn3K+qDTwc
+eoods7oBWRaUn1RCKAD3UClToZ1WfMRQNtIYrOAsqdveXpOWqioAP0wE5TTOuZIo
+GiWxRgIsc7TNtOmNBv+chCdbNP0emxdyjJUIGb7DFnfCw47EjHnn8Guc13uXaATN
+B2ZXgoUCgYAGa13P0ggUf5BMJpBd8S08jKRyvZb1CDXcUCuGtk2yEx45ern9U5WY
+zJ13E5z9MKKO8nkGBqrRfjJa8Xhxk4HKNFuzHEet5lvNE7IKCF4YQRb0ZBhnb/78
++4ZKjFki1RrWRNSw9TdvrK6qaDKgTtCTtfRVXAYQXUgq7lSFOTtL3A==
+-----END RSA PRIVATE KEY-----
+EOS
+ end
+
+ let(:valid_cert_but_indented) do
+ valid_cert.gsub(/^/, ' ')
+ end
+
+ let(:valid_key_but_indented) do
+ valid_key.gsub(/^/, ' ')
+ end
+
+ let(:malformed_cert) do
+ truncate_middle(valid_cert)
+ end
+
+ let(:malformed_key) do
+ truncate_middle(valid_key)
+ end
+
+ let(:bad_cert) do
+ 'foo'
+ end
+
+ let(:bad_key) do
+ 'bar'
+ end
+
+ context 'function signature validation' 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(0, 1, 2, 3).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+ end
+
+ context 'valid input' do
+ describe 'valid certificate and key' do
+ it { is_expected.to run.with_params(valid_cert, valid_key) }
+ end
+ end
+
+ context 'bad input' do
+ describe 'valid certificate, valid but indented key' do
+ it { is_expected.to run.with_params(valid_cert, valid_key_but_indented).and_raise_error(Puppet::ParseError, /Not a valid RSA key/) }
+ end
+
+ describe 'valid certificate, malformed key' do
+ it { is_expected.to run.with_params(valid_cert, malformed_key).and_raise_error(Puppet::ParseError, /Not a valid RSA key/) }
+ end
+
+ describe 'valid certificate, bad key' do
+ it { is_expected.to run.with_params(valid_cert, bad_key).and_raise_error(Puppet::ParseError, /Not a valid RSA key/) }
+ end
+
+ describe 'valid but indented certificate, valid key' do
+ it { is_expected.to run.with_params(valid_cert_but_indented, valid_key).and_raise_error(Puppet::ParseError, /Not a valid x509 certificate/) }
+ end
+
+ describe 'malformed certificate, valid key' do
+ it { is_expected.to run.with_params(malformed_cert, valid_key).and_raise_error(Puppet::ParseError, /Not a valid x509 certificate/) }
+ end
+
+ describe 'bad certificate, valid key' do
+ it { is_expected.to run.with_params(bad_cert, valid_key).and_raise_error(Puppet::ParseError, /Not a valid x509 certificate/) }
+ end
+
+ describe 'validate certificate and key; certficate not signed by key' do
+ it { is_expected.to run.with_params(valid_cert, another_valid_key).and_raise_error(Puppet::ParseError, /Certificate signature does not match supplied key/) }
+ end
+
+ describe 'valid cert and key but arguments in wrong order' do
+ it { is_expected.to run.with_params(valid_key, valid_cert).and_raise_error(Puppet::ParseError, /Not a valid x509 certificate/) }
+ end
+
+ describe 'non-string arguments' do
+ it { is_expected.to run.with_params({}, {}).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params(1, 1).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params(true, true).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params("foo", {}).and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params(1, "bar").and_raise_error(Puppet::ParseError, /is not a string/) }
+ it { is_expected.to run.with_params("baz", true).and_raise_error(Puppet::ParseError, /is not a string/) }
+ end
+ end
+
+ def truncate_middle(string)
+ chars_to_truncate = 48
+ middle = (string.length / 2).floor
+ start_pos = middle - (chars_to_truncate / 2)
+ end_pos = middle + (chars_to_truncate / 2)
+
+ string[start_pos...end_pos] = ''
+ return string
+ end
+end
diff --git a/spec/functions/values_at_spec.rb b/spec/functions/values_at_spec.rb
index 86e3c31..a8348f3 100755
--- a/spec/functions/values_at_spec.rb
+++ b/spec/functions/values_at_spec.rb
@@ -1,38 +1,49 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the values_at function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("values_at")).to eq("function_values_at")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_values_at([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should raise a ParseError if you try to use a range where stop is greater then start" do
- expect { scope.function_values_at([['a','b'],["3-1"]]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return a value at from an array" do
- result = scope.function_values_at([['a','b','c'],"1"])
- expect(result).to(eq(['b']))
- end
-
- it "should return a value at from an array when passed a range" do
- result = scope.function_values_at([['a','b','c'],"0-1"])
- expect(result).to(eq(['a','b']))
+describe 'values_at' do
+ describe 'signature validation' 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 {
+ pending("Current implementation ignores parameters after the first two.")
+ is_expected.to run.with_params([], 0, 1).and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params('', 1).and_raise_error(Puppet::ParseError, /Requires array/i) }
+ it { is_expected.to run.with_params({}, 1).and_raise_error(Puppet::ParseError, /Requires array/i) }
+ it { is_expected.to run.with_params(true, 1).and_raise_error(Puppet::ParseError, /Requires array/i) }
+ it { is_expected.to run.with_params(1, 1).and_raise_error(Puppet::ParseError, /Requires array/i) }
+ it { is_expected.to run.with_params([0,1,2], 'two').and_raise_error(Puppet::ParseError, /Unknown format of given index/) }
+ it { is_expected.to run.with_params([0,1,2], []).and_raise_error(Puppet::ParseError, /provide at least one positive index/) }
+ it { is_expected.to run.with_params([0,1,2], '-1-1').and_raise_error(Puppet::ParseError, /Unknown format of given index/) }
+ it { is_expected.to run.with_params([0,1,2], '2-1').and_raise_error(Puppet::ParseError, /Stop index in given indices range is smaller than the start index/) }
end
- it "should return chosen values from an array when passed number of indexes" do
- result = scope.function_values_at([['a','b','c'],["0","2"]])
- expect(result).to(eq(['a','c']))
+ context 'when requesting a single item' do
+ it { is_expected.to run.with_params([0, 1, 2], -1).and_raise_error(Puppet::ParseError, /Unknown format of given index/) }
+ it { is_expected.to run.with_params([0, 1, 2], 0).and_return([0]) }
+ it { is_expected.to run.with_params([0, 1, 2], 1).and_return([1]) }
+ it { is_expected.to run.with_params([0, 1, 2], [1]).and_return([1]) }
+ it { is_expected.to run.with_params([0, 1, 2], '1').and_return([1]) }
+ it { is_expected.to run.with_params([0, 1, 2], '1-1').and_return([1]) }
+ it { is_expected.to run.with_params([0, 1, 2], 2).and_return([2]) }
+ it { is_expected.to run.with_params([0, 1, 2], 3).and_raise_error(Puppet::ParseError, /index exceeds array size/) }
end
- it "should return chosen values from an array when passed ranges and multiple indexes" do
- result = scope.function_values_at([['a','b','c','d','e','f','g'],["0","2","4-5"]])
- expect(result).to(eq(['a','c','e','f']))
+ context 'when requesting multiple items' do
+ it { is_expected.to run.with_params([0, 1, 2], [1, -1]).and_raise_error(Puppet::ParseError, /Unknown format of given index/) }
+ it { is_expected.to run.with_params([0, 1, 2], [0, 2]).and_return([0, 2]) }
+ it { is_expected.to run.with_params([0, 1, 2], ['0-2', 1, 2]).and_return([0, 1, 2, 1, 2]) }
+ it { is_expected.to run.with_params([0, 1, 2], [3, 2]).and_raise_error(Puppet::ParseError, /index exceeds array size/) }
+
+ describe 'different range syntaxes' do
+ it { is_expected.to run.with_params([0, 1, 2], '0-2').and_return([0, 1, 2]) }
+ it { is_expected.to run.with_params([0, 1, 2], '0..2').and_return([0, 1, 2]) }
+ it { is_expected.to run.with_params([0, 1, 2], '0...2').and_return([0, 1]) }
+ it {
+ pending('fix this bounds check')
+ is_expected.to run.with_params([0, 1, 2], '0...3').and_return([0, 1, 2])
+ }
+ end
end
end
diff --git a/spec/functions/values_spec.rb b/spec/functions/values_spec.rb
index 08d21b0..4abf0bd 100755
--- a/spec/functions/values_spec.rb
+++ b/spec/functions/values_spec.rb
@@ -1,31 +1,19 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the values function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("values")).to eq("function_values")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_values([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should return values from a hash" do
- result = scope.function_values([{'a'=>'1','b'=>'2','c'=>'3'}])
- # =~ is the RSpec::Matchers::MatchArray matcher.
- # A.K.A. "array with same elements" (multiset) matching
- expect(result).to match_array(%w{ 1 2 3 })
- end
-
- it "should return a multiset" do
- result = scope.function_values([{'a'=>'1','b'=>'3','c'=>'3'}])
- expect(result).to match_array(%w{ 1 3 3 })
- expect(result).not_to match_array(%w{ 1 3 })
- end
-
- it "should raise a ParseError unless a Hash is provided" do
- expect { scope.function_values([['a','b','c']]) }.to( raise_error(Puppet::ParseError))
+describe 'values' 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 {
+ pending("Current implementation ignores parameters after the first.")
+ is_expected.to run.with_params({}, 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params('').and_raise_error(Puppet::ParseError, /Requires hash to work with/) }
+ it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires hash to work with/) }
+ it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError, /Requires hash to work with/) }
+ it { is_expected.to run.with_params({}).and_return([]) }
+ it { is_expected.to run.with_params({ 'key' => 'value' }).and_return(['value']) }
+ it 'should return the array of values' do
+ result = subject.call([{ 'key1' => 'value1', 'key2' => 'value2', 'duplicate_value_key' => 'value2' }])
+ expect(result).to match_array(['value1', 'value2', 'value2'])
end
end
diff --git a/spec/functions/zip_spec.rb b/spec/functions/zip_spec.rb
index f265fce..abca7ee 100755
--- a/spec/functions/zip_spec.rb
+++ b/spec/functions/zip_spec.rb
@@ -1,31 +1,15 @@
-#! /usr/bin/env ruby -S rspec
require 'spec_helper'
-describe "the zip function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_zip([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should be able to zip an array" do
- result = scope.function_zip([['1','2','3'],['4','5','6']])
- expect(result).to(eq([["1", "4"], ["2", "5"], ["3", "6"]]))
- result = scope.function_zip([['1','2','3'],['4','5','6'], false])
- result.should(eq([["1", "4"], ["2", "5"], ["3", "6"]]))
- end
-
- it "should be able to zip an array and flatten" do
- result = scope.function_zip([['1','2','3'],['4','5','6'], true])
- result.should(eq(["1", "4", "2", "5", "3", "6"]))
- end
-
- it "should accept objects which extend String for the second argument" do
- class AlsoString < String
- end
-
- value = AlsoString.new('false')
- result = scope.function_zip([['1','2','3'],['4','5','6'],value])
- result.should(eq([["1", "4"], ["2", "5"], ["3", "6"]]))
- end
+describe 'zip' 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 {
+ pending("Current implementation ignores parameters after the third.")
+ is_expected.to run.with_params([], [], true, []).and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+ }
+ it { is_expected.to run.with_params([], []).and_return([]) }
+ it { is_expected.to run.with_params([1,2,3], [4,5,6]).and_return([[1,4], [2,5], [3,6]]) }
+ it { is_expected.to run.with_params([1,2,3], [4,5,6], false).and_return([[1,4], [2,5], [3,6]]) }
+ it { is_expected.to run.with_params([1,2,3], [4,5,6], true).and_return([1, 4, 2, 5, 3, 6]) }
end
diff --git a/spec/lib/puppet_spec/compiler.rb b/spec/lib/puppet_spec/compiler.rb
deleted file mode 100755
index 2f0ae4d..0000000
--- a/spec/lib/puppet_spec/compiler.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-module PuppetSpec::Compiler
- def compile_to_catalog(string, node = Puppet::Node.new('foonode'))
- Puppet[:code] = string
- Puppet::Parser::Compiler.compile(node)
- end
-
- def compile_to_ral(manifest)
- catalog = compile_to_catalog(manifest)
- ral = catalog.to_ral
- ral.finalize
- ral
- end
-
- def compile_to_relationship_graph(manifest, prioritizer = Puppet::Graph::SequentialPrioritizer.new)
- ral = compile_to_ral(manifest)
- graph = Puppet::Graph::RelationshipGraph.new(prioritizer)
- graph.populate_from(ral)
- graph
- end
-
- if Puppet.version.to_f >= 3.3
- def apply_compiled_manifest(manifest, prioritizer = Puppet::Graph::SequentialPrioritizer.new)
- transaction = Puppet::Transaction.new(compile_to_ral(manifest),
- Puppet::Transaction::Report.new("apply"),
- prioritizer)
- transaction.evaluate
- transaction.report.finalize_report
-
- transaction
- end
- else
- def apply_compiled_manifest(manifest)
- transaction = Puppet::Transaction.new(compile_to_ral(manifest), Puppet::Transaction::Report.new("apply"))
- transaction.evaluate
- transaction.report.finalize_report
-
- transaction
- end
- end
-
- def order_resources_traversed_in(relationships)
- order_seen = []
- relationships.traverse { |resource| order_seen << resource.ref }
- order_seen
- end
-end
diff --git a/spec/lib/puppet_spec/database.rb b/spec/lib/puppet_spec/database.rb
deleted file mode 100755
index f5c2341..0000000
--- a/spec/lib/puppet_spec/database.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-# This just makes some nice things available at global scope, and for setup of
-# tests to use a real fake database, rather than a fake stubs-that-don't-work
-# version of the same. Fun times.
-def sqlite?
- if $sqlite.nil?
- begin
- require 'sqlite3'
- $sqlite = true
- rescue LoadError
- $sqlite = false
- end
- end
- $sqlite
-end
-
-def can_use_scratch_database?
- sqlite? and Puppet.features.rails?
-end
-
-
-# This is expected to be called in your `before :each` block, and will get you
-# ready to roll with a serious database and all. Cleanup is handled
-# automatically for you. Nothing to do there.
-def setup_scratch_database
- Puppet[:dbadapter] = 'sqlite3'
- Puppet[:dblocation] = ':memory:'
- Puppet[:railslog] = PuppetSpec::Files.tmpfile('storeconfigs.log')
- Puppet::Rails.init
-end
diff --git a/spec/lib/puppet_spec/files.rb b/spec/lib/puppet_spec/files.rb
deleted file mode 100755
index 71b38ff..0000000
--- a/spec/lib/puppet_spec/files.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-require 'fileutils'
-require 'tempfile'
-require 'tmpdir'
-require 'pathname'
-
-# A support module for testing files.
-module PuppetSpec::Files
- def self.cleanup
- $global_tempfiles ||= []
- while path = $global_tempfiles.pop do
- begin
- Dir.unstub(:entries)
- FileUtils.rm_rf path, :secure => true
- rescue Errno::ENOENT
- # nothing to do
- end
- end
- end
-
- def make_absolute(path) PuppetSpec::Files.make_absolute(path) end
- def self.make_absolute(path)
- path = File.expand_path(path)
- path[0] = 'c' if Puppet.features.microsoft_windows?
- path
- end
-
- def tmpfile(name, dir = nil) PuppetSpec::Files.tmpfile(name, dir) end
- def self.tmpfile(name, dir = nil)
- # Generate a temporary file, just for the name...
- source = dir ? Tempfile.new(name, dir) : Tempfile.new(name)
- path = source.path
- source.close!
-
- record_tmp(File.expand_path(path))
-
- path
- end
-
- def file_containing(name, contents) PuppetSpec::Files.file_containing(name, contents) end
- def self.file_containing(name, contents)
- file = tmpfile(name)
- File.open(file, 'wb') { |f| f.write(contents) }
- file
- end
-
- def tmpdir(name) PuppetSpec::Files.tmpdir(name) end
- def self.tmpdir(name)
- dir = Dir.mktmpdir(name)
-
- record_tmp(dir)
-
- dir
- end
-
- def self.record_tmp(tmp)
- # ...record it for cleanup,
- $global_tempfiles ||= []
- $global_tempfiles << tmp
- end
-end
diff --git a/spec/lib/puppet_spec/fixtures.rb b/spec/lib/puppet_spec/fixtures.rb
deleted file mode 100755
index 81e9775..0000000
--- a/spec/lib/puppet_spec/fixtures.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-module PuppetSpec::Fixtures
- def fixtures(*rest)
- File.join(PuppetSpec::FIXTURE_DIR, *rest)
- end
- def my_fixture_dir
- callers = caller
- while line = callers.shift do
- next unless found = line.match(%r{/spec/(.*)_spec\.rb:})
- return fixtures(found[1])
- end
- fail "sorry, I couldn't work out your path from the caller stack!"
- end
- def my_fixture(name)
- file = File.join(my_fixture_dir, name)
- unless File.readable? file then
- fail Puppet::DevError, "fixture '#{name}' for #{my_fixture_dir} is not readable"
- end
- return file
- end
- def my_fixtures(glob = '*', flags = 0)
- files = Dir.glob(File.join(my_fixture_dir, glob), flags)
- unless files.length > 0 then
- fail Puppet::DevError, "fixture '#{glob}' for #{my_fixture_dir} had no files!"
- end
- block_given? and files.each do |file| yield file end
- files
- end
-end
diff --git a/spec/lib/puppet_spec/matchers.rb b/spec/lib/puppet_spec/matchers.rb
deleted file mode 100755
index 093d77c..0000000
--- a/spec/lib/puppet_spec/matchers.rb
+++ /dev/null
@@ -1,121 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-require 'stringio'
-
-########################################################################
-# Backward compatibility for Jenkins outdated environment.
-module RSpec
- module Matchers
- module BlockAliases
- alias_method :to, :should unless method_defined? :to
- alias_method :to_not, :should_not unless method_defined? :to_not
- alias_method :not_to, :should_not unless method_defined? :not_to
- end
- end
-end
-
-
-########################################################################
-# Custom matchers...
-RSpec::Matchers.define :have_matching_element do |expected|
- match do |actual|
- actual.any? { |item| item =~ expected }
- end
-end
-
-
-RSpec::Matchers.define :exit_with do |expected|
- actual = nil
- match do |block|
- begin
- block.call
- rescue SystemExit => e
- actual = e.status
- end
- actual and actual == expected
- end
- failure_message_for_should do |block|
- "expected exit with code #{expected} but " +
- (actual.nil? ? " exit was not called" : "we exited with #{actual} instead")
- end
- failure_message_for_should_not do |block|
- "expected that exit would not be called with #{expected}"
- end
- description do
- "expect exit with #{expected}"
- end
-end
-
-class HavePrintedMatcher
- attr_accessor :expected, :actual
-
- def initialize(expected)
- case expected
- when String, Regexp
- @expected = expected
- else
- @expected = expected.to_s
- end
- end
-
- def matches?(block)
- begin
- $stderr = $stdout = StringIO.new
- $stdout.set_encoding('UTF-8') if $stdout.respond_to?(:set_encoding)
- block.call
- $stdout.rewind
- @actual = $stdout.read
- ensure
- $stdout = STDOUT
- $stderr = STDERR
- end
-
- if @actual then
- case @expected
- when String
- @actual.include? @expected
- when Regexp
- @expected.match @actual
- end
- else
- false
- end
- end
-
- def failure_message_for_should
- if @actual.nil? then
- "expected #{@expected.inspect}, but nothing was printed"
- else
- "expected #{@expected.inspect} to be printed; got:\n#{@actual}"
- end
- end
-
- def failure_message_for_should_not
- "expected #{@expected.inspect} to not be printed; got:\n#{@actual}"
- end
-
- def description
- "expect #{@expected.inspect} to be printed"
- end
-end
-
-def have_printed(what)
- HavePrintedMatcher.new(what)
-end
-
-RSpec::Matchers.define :equal_attributes_of do |expected|
- match do |actual|
- actual.instance_variables.all? do |attr|
- actual.instance_variable_get(attr) == expected.instance_variable_get(attr)
- end
- end
-end
-
-RSpec::Matchers.define :be_one_of do |*expected|
- match do |actual|
- expected.include? actual
- end
-
- failure_message_for_should do |actual|
- "expected #{actual.inspect} to be one of #{expected.map(&:inspect).join(' or ')}"
- end
-end
diff --git a/spec/lib/puppet_spec/modules.rb b/spec/lib/puppet_spec/modules.rb
deleted file mode 100755
index 910c6d9..0000000
--- a/spec/lib/puppet_spec/modules.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-module PuppetSpec::Modules
- class << self
- def create(name, dir, options = {})
- module_dir = File.join(dir, name)
- FileUtils.mkdir_p(module_dir)
-
- environment = options[:environment]
-
- if metadata = options[:metadata]
- metadata[:source] ||= 'github'
- metadata[:author] ||= 'puppetlabs'
- metadata[:version] ||= '9.9.9'
- metadata[:license] ||= 'to kill'
- metadata[:dependencies] ||= []
-
- metadata[:name] = "#{metadata[:author]}/#{name}"
-
- File.open(File.join(module_dir, 'metadata.json'), 'w') do |f|
- f.write(metadata.to_pson)
- end
- end
-
- Puppet::Module.new(name, module_dir, environment)
- end
- end
-end
diff --git a/spec/lib/puppet_spec/pops.rb b/spec/lib/puppet_spec/pops.rb
deleted file mode 100755
index e056a52..0000000
--- a/spec/lib/puppet_spec/pops.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-module PuppetSpec::Pops
- extend RSpec::Matchers::DSL
-
- # Checks if an Acceptor has a specific issue in its list of diagnostics
- matcher :have_issue do |expected|
- match do |actual|
- actual.diagnostics.index { |i| i.issue == expected } != nil
- end
- failure_message_for_should do |actual|
- "expected Acceptor[#{actual.diagnostics.collect { |i| i.issue.issue_code }.join(',')}] to contain issue #{expected.issue_code}"
- end
- failure_message_for_should_not do |actual|
- "expected Acceptor[#{actual.diagnostics.collect { |i| i.issue.issue_code }.join(',')}] to not contain issue #{expected.issue_code}"
- end
- end
-end
diff --git a/spec/lib/puppet_spec/scope.rb b/spec/lib/puppet_spec/scope.rb
deleted file mode 100755
index 3847ede..0000000
--- a/spec/lib/puppet_spec/scope.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-
-module PuppetSpec::Scope
- # Initialize a new scope suitable for testing.
- #
- def create_test_scope_for_node(node_name)
- node = Puppet::Node.new(node_name)
- compiler = Puppet::Parser::Compiler.new(node)
- scope = Puppet::Parser::Scope.new(compiler)
- scope.source = Puppet::Resource::Type.new(:node, node_name)
- scope.parent = compiler.topscope
- scope
- end
-
-end \ No newline at end of file
diff --git a/spec/lib/puppet_spec/settings.rb b/spec/lib/puppet_spec/settings.rb
deleted file mode 100755
index 8ddcb97..0000000
--- a/spec/lib/puppet_spec/settings.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-module PuppetSpec::Settings
-
- # It would probably be preferable to refactor defaults.rb such that the real definitions of
- # these settings were available as a variable, which was then accessible for use during tests.
- # However, I'm not doing that yet because I don't want to introduce any additional moving parts
- # to this already very large changeset.
- # Would be nice to clean this up later. --cprice 2012-03-20
- TEST_APP_DEFAULT_DEFINITIONS = {
- :name => { :default => "test", :desc => "name" },
- :logdir => { :type => :directory, :default => "test", :desc => "logdir" },
- :confdir => { :type => :directory, :default => "test", :desc => "confdir" },
- :vardir => { :type => :directory, :default => "test", :desc => "vardir" },
- :rundir => { :type => :directory, :default => "test", :desc => "rundir" },
- }
-end
diff --git a/spec/lib/puppet_spec/verbose.rb b/spec/lib/puppet_spec/verbose.rb
deleted file mode 100755
index b2683df..0000000
--- a/spec/lib/puppet_spec/verbose.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-# Support code for running stuff with warnings disabled.
-module Kernel
- def with_verbose_disabled
- verbose, $VERBOSE = $VERBOSE, nil
- result = yield
- $VERBOSE = verbose
- return result
- end
-end
diff --git a/spec/spec.opts b/spec/spec.opts
deleted file mode 100644
index 91cd642..0000000
--- a/spec/spec.opts
+++ /dev/null
@@ -1,6 +0,0 @@
---format
-s
---colour
---loadby
-mtime
---backtrace
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index b490ca3..22d5d68 100755
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,34 +1,8 @@
-#! /usr/bin/env ruby -S rspec
-dir = File.expand_path(File.dirname(__FILE__))
-$LOAD_PATH.unshift File.join(dir, 'lib')
-
-# So everyone else doesn't have to include this base constant.
-module PuppetSpec
- FIXTURE_DIR = File.join(dir = File.expand_path(File.dirname(__FILE__)), "fixtures") unless defined?(FIXTURE_DIR)
-end
-
-require 'puppet'
-require 'rspec-puppet'
+#This file is generated by ModuleSync, do not edit.
require 'puppetlabs_spec_helper/module_spec_helper'
-require 'puppet_spec/verbose'
-require 'puppet_spec/files'
-require 'puppet_spec/settings'
-require 'puppet_spec/fixtures'
-require 'puppet_spec/matchers'
-require 'puppet_spec/database'
-require 'monkey_patches/alias_should_to_must'
-require 'mocha/setup'
-
-
-RSpec.configure do |config|
- config.before :each do
- # Ensure that we don't accidentally cache facts and environment between
- # test cases. This requires each example group to explicitly load the
- # facts being exercised with something like
- # Facter.collection.loader.load(:ipaddress)
- Facter::Util::Loader.any_instance.stubs(:load_all)
- Facter.clear
- Facter.clear_messages
- end
+# put local configuration and setup into spec_helper_local
+begin
+ require 'spec_helper_local'
+rescue LoadError
end
diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb
index 3203ce9..8a1907f 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'] ? ENV['PUPPET_VERSION'] : '3.7.2'),
- }
-
- 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
@@ -33,7 +15,7 @@ RSpec.configure do |c|
# Configure all nodes in nodeset
c.before :suite do
- if ENV['FUTURE_PARSER'] == 'true'
+ if ENV['FUTURE_PARSER'] == 'yes'
default[:default_apply_opts] ||= {}
default[:default_apply_opts].merge!({:parser => 'future'})
end
@@ -43,8 +25,46 @@ RSpec.configure do |c|
end
def is_future_parser_enabled?
- if default[:default_apply_opts]
+ if default[:type] == 'aio' || ENV['PUPPET_INSTALL_TYPE'] == 'agent'
+ return true
+ elsif default[:default_apply_opts]
return default[:default_apply_opts][:parser] == 'future'
end
return false
end
+
+def get_puppet_version
+ (on default, puppet('--version')).output.chomp
+end
+
+RSpec.shared_context "with faked facts" do
+ let(:facts_d) do
+ puppet_version = get_puppet_version
+ 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/spec_helper_local.rb b/spec/spec_helper_local.rb
new file mode 100644
index 0000000..616490c
--- /dev/null
+++ b/spec/spec_helper_local.rb
@@ -0,0 +1,31 @@
+# automatically load any shared examples or contexts
+Dir["./spec/support/**/*.rb"].sort.each { |f| require f }
+
+# hack to enable all the expect syntax (like allow_any_instance_of) in rspec-puppet examples
+RSpec::Mocks::Syntax.enable_expect(RSpec::Puppet::ManifestMatchers)
+
+RSpec.configure do |config|
+ # supply tests with a possibility to test for the future parser
+ config.add_setting :puppet_future
+ config.puppet_future = Puppet.version.to_f >= 4.0
+
+ config.before :each do
+ # Ensure that we don't accidentally cache facts and environment between
+ # test cases. This requires each example group to explicitly load the
+ # facts being exercised with something like
+ # Facter.collection.loader.load(:ipaddress)
+ Facter.clear
+ Facter.clear_messages
+
+ RSpec::Mocks.setup
+ end
+
+ config.after :each do
+ RSpec::Mocks.verify
+ RSpec::Mocks.teardown
+ end
+end
+
+# Helper class to test handling of arguments which are derived from string
+class AlsoString < String
+end
diff --git a/spec/support/shared_data.rb b/spec/support/shared_data.rb
new file mode 100644
index 0000000..ea9b7a0
--- /dev/null
+++ b/spec/support/shared_data.rb
@@ -0,0 +1,38 @@
+module SharedData
+ IPV4_PATTERNS = [
+ '0.0.0.0',
+ '1.2.3.4',
+ '10.10.10.10',
+ '127.0.0.1',
+ '192.88.99.0',
+ '194.232.104.150',
+ '224.0.0.0',
+ '244.24.24.24',
+ '255.255.255.255',
+ '8.8.8.8',
+ '8.8.8.8/0',
+ '8.8.8.8/16',
+ '8.8.8.8/255.255.0.0',
+ '8.8.8.8/32',
+ ]
+ IPV4_NEGATIVE_PATTERNS = [
+ '',
+ '0000',
+ '0.0.0.0.',
+ '0.0.0.0./0.0.0.0.',
+ '0.0.0.0./1',
+ '0.0.0.0.0',
+ '0.0.0.0/0.0.0.0.',
+ '0.0.0.256',
+ '0.0.0',
+ '1.2.3.4.5',
+ '1.2.3',
+ '10.010.10.10',
+ '2001:0db8:85a3:0000:0000:8a2e:0370:73342001:0db8:85a3:0000:0000:8a2e:0370:7334',
+ '4.4.4',
+ '77',
+ '9999.9999.9999.9999',
+ 'affe::beef',
+ 'nope',
+ ]
+end
diff --git a/spec/unit/ensure_resources_spec.rb b/spec/unit/ensure_resources_spec.rb
new file mode 100644
index 0000000..aea723e
--- /dev/null
+++ b/spec/unit/ensure_resources_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe 'test::ensure_resources', type: :class do
+ let(:params) {{ resource_type: 'user', title_hash: title_param, attributes_hash: {'ensure' => 'present'} }}
+
+ describe 'given a title hash of multiple resources' do
+
+ let(:title_param) { {'dan' => { 'gid' => 'mygroup', 'uid' => '600' }, 'alex' => { 'gid' => 'mygroup', 'uid' => '700'}} }
+
+ it { is_expected.to compile }
+ it { is_expected.to contain_user('dan').with({ 'gid' => 'mygroup', 'uid' => '600', 'ensure' => 'present'}) }
+ it { is_expected.to contain_user('alex').with({ 'gid' => 'mygroup', 'uid' => '700', 'ensure' => 'present'}) }
+ end
+
+ describe 'given a title hash of a single resource' do
+
+ let(:title_param) { {'dan' => { 'gid' => 'mygroup', 'uid' => '600' }} }
+
+ it { is_expected.to compile }
+ it { is_expected.to contain_user('dan').with({ 'gid' => 'mygroup', 'uid' => '600', 'ensure' => 'present'}) }
+ end
+end
diff --git a/spec/unit/facter/package_provider_spec.rb b/spec/unit/facter/package_provider_spec.rb
new file mode 100644
index 0000000..3954faf
--- /dev/null
+++ b/spec/unit/facter/package_provider_spec.rb
@@ -0,0 +1,44 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+require 'puppet/type'
+require 'puppet/type/package'
+
+describe 'package_provider', :type => :fact do
+ before { Facter.clear }
+ after { Facter.clear }
+
+ ['4.2.2', '3.7.1 (Puppet Enterprise 3.2.1)'].each do |puppetversion|
+ describe "on puppet ''#{puppetversion}''" do
+ before :each do
+ Facter.stubs(:value).returns puppetversion
+ end
+
+ context "darwin" do
+ it "should return pkgdmg" do
+ provider = Puppet::Type.type(:package).provider(:pkgdmg)
+ Puppet::Type.type(:package).stubs(:defaultprovider).returns provider
+
+ expect(Facter.fact(:package_provider).value).to eq('pkgdmg')
+ end
+ end
+
+ context "centos 7" do
+ it "should return yum" do
+ provider = Puppet::Type.type(:package).provider(:yum)
+ Puppet::Type.type(:package).stubs(:defaultprovider).returns provider
+
+ expect(Facter.fact(:package_provider).value).to eq('yum')
+ end
+ end
+
+ context "ubuntu" do
+ it "should return apt" do
+ provider = Puppet::Type.type(:package).provider(:apt)
+ Puppet::Type.type(:package).stubs(:defaultprovider).returns provider
+
+ expect(Facter.fact(:package_provider).value).to eq('apt')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/unit/facter/pe_version_spec.rb b/spec/unit/facter/pe_version_spec.rb
index 4d0349e..c11a1cd 100755
--- a/spec/unit/facter/pe_version_spec.rb
+++ b/spec/unit/facter/pe_version_spec.rb
@@ -14,6 +14,17 @@ describe "PE Version specs" do
Facter.collection.loader.load(:pe_version)
end
end
+
+ context "When puppetversion is nil" do
+ before :each do
+ Facter.fact(:puppetversion).stubs(:value).returns(nil)
+ end
+
+ it "pe_version is nil" do
+ expect(Facter.fact(:puppetversion).value).to be_nil
+ expect(Facter.fact(:pe_version).value).to be_nil
+ end
+ end
context "If PE is installed" do
%w{ 2.6.1 2.10.300 }.each do |version|
@@ -73,4 +84,5 @@ describe "PE Version specs" do
expect(Facter.fact(:pe_patch_version).value).to be_nil
end
end
+
end
diff --git a/spec/unit/facter/root_home_spec.rb b/spec/unit/facter/root_home_spec.rb
index 98fe141..a5c2846 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/facter/service_provider_spec.rb b/spec/unit/facter/service_provider_spec.rb
new file mode 100644
index 0000000..ad8a5fc
--- /dev/null
+++ b/spec/unit/facter/service_provider_spec.rb
@@ -0,0 +1,37 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+require 'puppet/type'
+require 'puppet/type/service'
+
+describe 'service_provider', :type => :fact do
+ before { Facter.clear }
+ after { Facter.clear }
+
+ context "macosx" do
+ it "should return launchd" do
+ provider = Puppet::Type.type(:service).provider(:launchd)
+ Puppet::Type.type(:service).stubs(:defaultprovider).returns provider
+
+ expect(Facter.fact(:service_provider).value).to eq('launchd')
+ end
+ end
+
+ context "systemd" do
+ it "should return systemd" do
+ provider = Puppet::Type.type(:service).provider(:systemd)
+ Puppet::Type.type(:service).stubs(:defaultprovider).returns provider
+
+ expect(Facter.fact(:service_provider).value).to eq('systemd')
+ end
+ end
+
+ context "redhat" do
+ it "should return redhat" do
+ provider = Puppet::Type.type(:service).provider(:redhat)
+ Puppet::Type.type(:service).stubs(:defaultprovider).returns provider
+
+ expect(Facter.fact(:service_provider).value).to eq('redhat')
+ end
+ end
+
+end
diff --git a/spec/unit/facter/util/puppet_settings_spec.rb b/spec/unit/facter/util/puppet_settings_spec.rb
index c06137d..c278b79 100755
--- a/spec/unit/facter/util/puppet_settings_spec.rb
+++ b/spec/unit/facter/util/puppet_settings_spec.rb
@@ -25,6 +25,7 @@ describe Facter::Util::PuppetSettings do
before :each do
Puppet.expects(:[]).with(:vardir).returns vardir
end
+
it 'should yield to the block' do
subject.with_puppet { Puppet[:vardir] }
end
diff --git a/spec/unit/puppet/functions/type_of_spec.rb b/spec/unit/puppet/functions/type_of_spec.rb
deleted file mode 100644
index 8afb624..0000000
--- a/spec/unit/puppet/functions/type_of_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-
-require 'spec_helper'
-
-if ENV["FUTURE_PARSER"] == 'yes' or Puppet.version >= "4"
- require 'puppet/pops'
- require 'puppet/loaders'
-
- describe 'the type_of function' do
- before(:all) do
- loaders = Puppet::Pops::Loaders.new(Puppet::Node::Environment.create(:testing, [File.join(fixtures, "modules")]))
- Puppet.push_context({:loaders => loaders}, "test-examples")
- end
-
- after(:all) do
- Puppet::Pops::Loaders.clear
- Puppet::pop_context()
- end
-
- let(:func) do
- # Load the function from the environment modulepath's modules (ie, fixtures)
- Puppet.lookup(:loaders).private_environment_loader.load(:function, 'type_of')
- end
-
- it 'gives the type of a string' do
- expect(func.call({}, 'hello world')).to be_kind_of(Puppet::Pops::Types::PStringType)
- end
-
- it 'gives the type of an integer' do
- expect(func.call({}, 5)).to be_kind_of(Puppet::Pops::Types::PIntegerType)
- end
- end
-end
diff --git a/spec/unit/puppet/parser/functions/basename_spec.rb b/spec/unit/puppet/parser/functions/basename_spec.rb
deleted file mode 100755
index 8a2d0dc..0000000
--- a/spec/unit/puppet/parser/functions/basename_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-require 'spec_helper'
-
-describe "the basename function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- Puppet::Parser::Functions.function("basename").should == "function_basename"
- end
-
- it "should raise a ParseError if there is less than 1 argument" do
- lambda { scope.function_basename([]) }.should( raise_error(Puppet::ParseError))
- end
-
- it "should raise a ParseError if there are more than 2 arguments" do
- lambda { scope.function_basename(['a', 'b', 'c']) }.should( raise_error(Puppet::ParseError))
- end
-
- it "should return basename for an absolute path" do
- result = scope.function_basename(['/path/to/a/file.ext'])
- result.should(eq('file.ext'))
- end
-
- it "should return basename for a relative path" do
- result = scope.function_basename(['path/to/a/file.ext'])
- result.should(eq('file.ext'))
- end
-
- it "should strip extention when extension specified (absolute path)" do
- result = scope.function_basename(['/path/to/a/file.ext', '.ext'])
- result.should(eq('file'))
- end
-
- it "should strip extention when extension specified (relative path)" do
- result = scope.function_basename(['path/to/a/file.ext', '.ext'])
- result.should(eq('file'))
- end
-
- it "should complain about non-string first argument" do
- lambda { scope.function_basename([[]]) }.should( raise_error(Puppet::ParseError))
- end
-
- it "should complain about non-string second argument" do
- lambda { scope.function_basename(['/path/to/a/file.ext', []]) }.should( raise_error(Puppet::ParseError))
- end
-end
diff --git a/spec/unit/puppet/parser/functions/bool2str_spec.rb b/spec/unit/puppet/parser/functions/bool2str_spec.rb
deleted file mode 100755
index b878891..0000000
--- a/spec/unit/puppet/parser/functions/bool2str_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-require 'spec_helper'
-
-describe "the bool2str function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("bool2str")).to eq("function_bool2str")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_bool2str([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should convert true to 'true'" do
- result = scope.function_bool2str([true])
- expect(result).to(eq('true'))
- end
-
- it "should convert true to a string" do
- result = scope.function_bool2str([true])
- expect(result.class).to(eq(String))
- end
-
- it "should convert false to 'false'" do
- result = scope.function_bool2str([false])
- expect(result).to(eq('false'))
- end
-
- it "should convert false to a string" do
- result = scope.function_bool2str([false])
- expect(result.class).to(eq(String))
- end
-
- it "should not accept a string" do
- expect { scope.function_bool2str(["false"]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should not accept a nil value" do
- expect { scope.function_bool2str([nil]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should not accept an undef" do
- expect { scope.function_bool2str([:undef]) }.to( raise_error(Puppet::ParseError))
- end
-end
diff --git a/spec/unit/puppet/parser/functions/camelcase_spec.rb b/spec/unit/puppet/parser/functions/camelcase_spec.rb
deleted file mode 100755
index 70382ad..0000000
--- a/spec/unit/puppet/parser/functions/camelcase_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-#! /usr/bin/env ruby -S rspec
-require 'spec_helper'
-
-describe "the camelcase function" do
- let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
-
- it "should exist" do
- expect(Puppet::Parser::Functions.function("camelcase")).to eq("function_camelcase")
- end
-
- it "should raise a ParseError if there is less than 1 arguments" do
- expect { scope.function_camelcase([]) }.to( raise_error(Puppet::ParseError))
- end
-
- it "should capitalize the beginning of a normal string" do
- result = scope.function_camelcase(["abc"])
- expect(result).to(eq("Abc"))
- end
-
- it "should camelcase an underscore-delimited string" do
- result = scope.function_camelcase(["aa_bb_cc"])
- expect(result).to(eq("AaBbCc"))
- end
-end
diff --git a/spec/unit/puppet/parser/functions/enclose_ipv6_spec.rb b/spec/unit/puppet/parser/functions/enclose_ipv6_spec.rb
new file mode 100644
index 0000000..b162127
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/enclose_ipv6_spec.rb
@@ -0,0 +1,69 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+describe "the enclose_ipv6 function" do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ it "should exist" do
+ expect(Puppet::Parser::Functions.function("enclose_ipv6")).to eq("function_enclose_ipv6")
+ end
+
+ it "should raise a ParseError if there is less than 1 arguments" do
+ expect { scope.function_enclose_ipv6([]) }.to( raise_error(Puppet::ParseError) )
+ end
+
+ it "should raise a ParseError if there is more than 1 arguments" do
+ expect { scope.function_enclose_ipv6(['argument1','argument2']) }.to( raise_error(Puppet::ParseError) )
+ end
+
+ it "should raise a ParseError when given garbage" do
+ expect { scope.function_enclose_ipv6(['garbage']) }.to( raise_error(Puppet::ParseError) )
+ end
+
+ it "should raise a ParseError when given something else than a string or an array" do
+ expect { scope.function_enclose_ipv6([['1' => '127.0.0.1']]) }.to( raise_error(Puppet::ParseError) )
+ end
+
+ it "should not raise a ParseError when given a single ip string" do
+ expect { scope.function_enclose_ipv6(['127.0.0.1']) }.to_not raise_error
+ end
+
+ it "should not raise a ParseError when given * as ip string" do
+ expect { scope.function_enclose_ipv6(['*']) }.to_not raise_error
+ end
+
+ it "should not raise a ParseError when given an array of ip strings" do
+ expect { scope.function_enclose_ipv6([['127.0.0.1','fe80::1']]) }.to_not raise_error
+ end
+
+ it "should not raise a ParseError when given differently notations of ip addresses" do
+ expect { scope.function_enclose_ipv6([['127.0.0.1','fe80::1','[fe80::1]']]) }.to_not raise_error
+ end
+
+ it "should raise a ParseError when given a wrong ipv4 address" do
+ expect { scope.function_enclose_ipv6(['127..0.0.1']) }.to( raise_error(Puppet::ParseError) )
+ end
+
+ it "should raise a ParseError when given a ipv4 address with square brackets" do
+ expect { scope.function_enclose_ipv6(['[127.0.0.1]']) }.to( raise_error(Puppet::ParseError) )
+ end
+
+ it "should raise a ParseError when given a wrong ipv6 address" do
+ expect { scope.function_enclose_ipv6(['fe80:::1']) }.to( raise_error(Puppet::ParseError) )
+ end
+
+ it "should embrace ipv6 adresses within an array of ip addresses" do
+ result = scope.function_enclose_ipv6([['127.0.0.1','fe80::1','[fe80::2]']])
+ expect(result).to(eq(['127.0.0.1','[fe80::1]','[fe80::2]']))
+ end
+
+ it "should embrace a single ipv6 adresse" do
+ result = scope.function_enclose_ipv6(['fe80::1'])
+ expect(result).to(eq(['[fe80::1]']))
+ end
+
+ it "should not embrace a single ipv4 adresse" do
+ result = scope.function_enclose_ipv6(['127.0.0.1'])
+ expect(result).to(eq(['127.0.0.1']))
+ end
+end
diff --git a/spec/unit/puppet/parser/functions/is_absolute_path_spec.rb b/spec/unit/puppet/parser/functions/is_absolute_path_spec.rb
new file mode 100644
index 0000000..8931208
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/is_absolute_path_spec.rb
@@ -0,0 +1,86 @@
+require 'spec_helper'
+
+describe :is_absolute_path do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ let(:function_args) do
+ []
+ end
+
+ let(:function) do
+ scope.function_is_absolute_path(function_args)
+ end
+
+
+ describe 'validate arity' do
+ let(:function_args) do
+ [1,2]
+ end
+ it "should raise a ParseError if there is more than 1 arguments" do
+ lambda { function }.should( raise_error(ArgumentError))
+ end
+
+ end
+
+ it "should exist" do
+ Puppet::Parser::Functions.function(subject).should == "function_#{subject}"
+ end
+
+ # help enforce good function defination
+ it 'should contain arity' do
+
+ end
+
+ it "should raise a ParseError if there is less than 1 arguments" do
+ lambda { function }.should( raise_error(ArgumentError))
+ end
+
+
+ describe 'should retrun true' do
+ let(:return_value) do
+ true
+ end
+
+ describe 'windows' do
+ let(:function_args) do
+ ['c:\temp\test.txt']
+ end
+ it 'should return data' do
+ function.should eq(return_value)
+ end
+ end
+
+ describe 'non-windows' do
+ let(:function_args) do
+ ['/temp/test.txt']
+ end
+
+ it 'should return data' do
+ function.should eq(return_value)
+ end
+ end
+ end
+
+ describe 'should return false' do
+ let(:return_value) do
+ false
+ end
+ describe 'windows' do
+ let(:function_args) do
+ ['..\temp\test.txt']
+ end
+ it 'should return data' do
+ function.should eq(return_value)
+ end
+ end
+
+ describe 'non-windows' do
+ let(:function_args) do
+ ['../var/lib/puppet']
+ end
+ it 'should return data' do
+ function.should eq(return_value)
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/unit/puppet/provider/file_line/ruby_spec.rb b/spec/unit/puppet/provider/file_line/ruby_spec.rb
index d2a129c..1f41f62 100755
--- a/spec/unit/puppet/provider/file_line/ruby_spec.rb
+++ b/spec/unit/puppet/provider/file_line/ruby_spec.rb
@@ -36,8 +36,7 @@ describe provider_class do
expect(File.read(tmpfile).chomp).to eq('foo')
end
end
-
- context "when matching" do
+ 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:
@@ -46,12 +45,64 @@ describe provider_class do
@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*=.*$',
+ :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
+ # 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*=.*$',
+ }
)
@provider = provider_class.new(@resource)
end
@@ -69,11 +120,11 @@ describe provider_class do
it 'should replace all lines that matches' do
@resource = Puppet::Type::File_line.new(
{
- :name => 'foo',
- :path => @tmpfile,
- :line => 'foo = bar',
- :match => '^foo\s*=.*$',
- :multiple => true
+ :name => 'foo',
+ :path => @tmpfile,
+ :line => 'foo = bar',
+ :match => '^foo\s*=.*$',
+ :multiple => true,
}
)
@provider = provider_class.new(@resource)
@@ -89,11 +140,11 @@ describe provider_class do
expect {
@resource = Puppet::Type::File_line.new(
{
- :name => 'foo',
- :path => @tmpfile,
- :line => 'foo = bar',
- :match => '^foo\s*=.*$',
- :multiple => 'asgadga'
+ :name => 'foo',
+ :path => @tmpfile,
+ :line => 'foo = bar',
+ :match => '^foo\s*=.*$',
+ :multiple => 'asgadga',
}
)
}.to raise_error(Puppet::Error, /Invalid value "asgadga"\. Valid values are true, false\./)
@@ -140,7 +191,54 @@ describe provider_class do
let :provider do
provider_class.new(resource)
end
-
+ context 'match and after set' do
+ shared_context 'resource_create' do
+ let(:match) { '^foo2$' }
+ let(:after) { '^foo1$' }
+ let(:resource) {
+ Puppet::Type::File_line.new(
+ {
+ :name => 'foo',
+ :path => @tmpfile,
+ :line => 'inserted = line',
+ :after => after,
+ :match => match,
+ }
+ )
+ }
+ end
+ before :each do
+ File.open(@tmpfile, 'w') do |fh|
+ fh.write("foo1\nfoo2\nfoo = baz")
+ end
+ end
+ describe 'inserts at match' do
+ include_context 'resource_create'
+ it {
+ provider.create
+ expect(File.read(@tmpfile).chomp).to eq("foo1\ninserted = line\nfoo = baz")
+ }
+ end
+ describe 'inserts a new line after when no match' do
+ include_context 'resource_create' do
+ let(:match) { '^nevergoingtomatch$' }
+ end
+ it {
+ provider.create
+ expect(File.read(@tmpfile).chomp).to eq("foo1\ninserted = line\nfoo2\nfoo = baz")
+ }
+ end
+ describe 'append to end of file if no match for both after and match' do
+ include_context 'resource_create' do
+ let(:match) { '^nevergoingtomatch$' }
+ let(:after) { '^stillneverafter' }
+ end
+ it {
+ provider.create
+ expect(File.read(@tmpfile).chomp).to eq("foo1\nfoo2\nfoo = baz\ninserted = line")
+ }
+ end
+ end
context 'with one line matching the after expression' do
before :each do
File.open(@tmpfile, 'w') do |fh|
@@ -154,7 +252,7 @@ describe provider_class do
end
end
- context 'with two lines matching the after expression' do
+ context 'with multiple lines matching the after expression' do
before :each do
File.open(@tmpfile, 'w') do |fh|
fh.write("foo1\nfoo = blah\nfoo2\nfoo1\nfoo = baz")
@@ -164,6 +262,22 @@ describe provider_class do
it 'errors out stating "One or no line must match the pattern"' do
expect { provider.create }.to raise_error(Puppet::Error, /One or no line must match the pattern/)
end
+
+ it 'adds the line after all lines matching the after expression' do
+ @resource = Puppet::Type::File_line.new(
+ {
+ :name => 'foo',
+ :path => @tmpfile,
+ :line => 'inserted = line',
+ :after => '^foo1$',
+ :multiple => true,
+ }
+ )
+ @provider = provider_class.new(@resource)
+ expect(@provider.exists?).to be_nil
+ @provider.create
+ expect(File.read(@tmpfile).chomp).to eql("foo1\ninserted = line\nfoo = blah\nfoo2\nfoo1\ninserted = line\nfoo = baz")
+ end
end
context 'with no lines matching the after expression' do
@@ -194,7 +308,12 @@ describe provider_class do
@tmpfile = tmp.path
tmp.close!
@resource = Puppet::Type::File_line.new(
- {:name => 'foo', :path => @tmpfile, :line => 'foo', :ensure => 'absent' }
+ {
+ :name => 'foo',
+ :path => @tmpfile,
+ :line => 'foo',
+ :ensure => 'absent',
+ }
)
@provider = provider_class.new(@resource)
end
@@ -222,4 +341,107 @@ 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 find a line to match' do
+ File.open(@tmpfile, 'w') do |fh|
+ fh.write("foo1\nfoo\nfoo2")
+ end
+ expect(@provider.exists?).to be_truthy
+ 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_absence 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_absence 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..48e2670 100755
--- a/spec/unit/puppet/type/file_line_spec.rb
+++ b/spec/unit/puppet/type/file_line_spec.rb
@@ -41,14 +41,20 @@ describe Puppet::Type.type(:file_line) do
expect { file_line[:path] = 'file' }.to raise_error(Puppet::Error, /File paths must be fully qualified/)
end
it 'should require that a line is specified' do
- expect { Puppet::Type.type(:file_line).new(:name => 'foo', :path => '/tmp/file') }.to raise_error(Puppet::Error, /Both line and path are required attributes/)
+ expect { Puppet::Type.type(:file_line).new(:name => 'foo', :path => '/tmp/file') }.to raise_error(Puppet::Error, /line is a required attribute/)
+ end
+ it 'should not require that a line is specified when matching for absence' do
+ expect { Puppet::Type.type(:file_line).new(:name => 'foo', :path => '/tmp/file', :ensure => :absent, :match_for_absence => :true, :match => 'match') }.not_to raise_error
end
it 'should require that a file is specified' do
- expect { Puppet::Type.type(:file_line).new(:name => 'foo', :line => 'path') }.to raise_error(Puppet::Error, /Both line and path are required attributes/)
+ expect { Puppet::Type.type(:file_line).new(:name => 'foo', :line => 'path') }.to raise_error(Puppet::Error, /path is a required attribute/)
end
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
diff --git a/types/absolutepath.pp b/types/absolutepath.pp
new file mode 100644
index 0000000..70ec916
--- /dev/null
+++ b/types/absolutepath.pp
@@ -0,0 +1,2 @@
+# A strict absolutepath type
+type Stdlib::Absolutepath = Variant[Stdlib::Windowspath, Stdlib::Unixpath]
diff --git a/types/compat/absolute_path.pp b/types/compat/absolute_path.pp
new file mode 100644
index 0000000..d11784e
--- /dev/null
+++ b/types/compat/absolute_path.pp
@@ -0,0 +1,7 @@
+# Emulate the is_absolute_path and validate_absolute_path functions
+#
+# The first pattern is originally from is_absolute_path, which had it from 2.7.x's lib/puppet/util.rb Puppet::Util.absolute_path?
+# slash = '[\\\\/]'
+# name = '[^\\\\/]+'
+# %r!^(([A-Z]:#{slash})|(#{slash}#{slash}#{name}#{slash}#{name})|(#{slash}#{slash}\?#{slash}#{name}))!i,
+type Stdlib::Compat::Absolute_path = Variant[Pattern[/^(([a-zA-Z]:[\\\/])|([\\\/][\\\/][^\\\/]+[\\\/][^\\\/]+)|([\\\/][\\\/]\?[\\\/][^\\\/]+))/], Pattern[/^\//]]
diff --git a/types/compat/array.pp b/types/compat/array.pp
new file mode 100644
index 0000000..ba65dc4
--- /dev/null
+++ b/types/compat/array.pp
@@ -0,0 +1,2 @@
+# Emulate the is_array and validate_array functions
+type Stdlib::Compat::Array = Array[Any]
diff --git a/types/compat/bool.pp b/types/compat/bool.pp
new file mode 100644
index 0000000..5d8e27e
--- /dev/null
+++ b/types/compat/bool.pp
@@ -0,0 +1,2 @@
+# Emulate the is_bool and validate_bool functions
+type Stdlib::Compat::Bool = Boolean
diff --git a/types/compat/float.pp b/types/compat/float.pp
new file mode 100644
index 0000000..7f98bd2
--- /dev/null
+++ b/types/compat/float.pp
@@ -0,0 +1,19 @@
+# Emulate the is_float function
+# The regex is what's currently used in is_float
+# To keep your development moving forward, you can also add a deprecation warning using the Integer type:
+#
+# ```class example($value) { validate_float($value,) }```
+#
+# would turn into
+#
+# ```
+# class example(Stdlib::Compat::Float $value) {
+# validate_float($value, 10, 0)
+# assert_type(Integer[0, 10], $value) |$expected, $actual| {
+# warning("The 'value' parameter for the 'ntp' class has type ${actual}, but should be ${expected}.")
+# }
+# }
+# ```
+#
+# This allows you to find all places where a consumers of your code call it with unexpected values.
+type Stdlib::Compat::Float = Variant[Float, Pattern[/^-?(?:(?:[1-9]\d*)|0)(?:\.\d+)(?:[eE]-?\d+)?$/]]
diff --git a/types/compat/integer.pp b/types/compat/integer.pp
new file mode 100644
index 0000000..e5cadb6
--- /dev/null
+++ b/types/compat/integer.pp
@@ -0,0 +1,23 @@
+# Emulate the is_integer and validate_integer functions
+# The regex is what's currently used in is_integer
+# validate_numeric also allows range checking, which cannot be mapped to the string parsing inside the function.
+# For full backwards compatibility, you will need to keep the validate_numeric call around to catch everything.
+# To keep your development moving forward, you can also add a deprecation warning using the Integer type:
+#
+# ```class example($value) { validate_integer($value, 10, 0) }```
+#
+# would turn into
+#
+# ```
+# class example(Stdlib::Compat::Integer $value) {
+# validate_numeric($value, 10, 0)
+# assert_type(Integer[0, 10], $value) |$expected, $actual| {
+# warning("The 'value' parameter for the 'ntp' class has type ${actual}, but should be ${expected}.")
+# }
+# }
+# ```
+#
+# > Note that you need to use Variant[Integer[0, 10], Float[0, 10]] if you want to match both integers and floating point numbers.
+#
+# This allows you to find all places where a consumers of your code call it with unexpected values.
+type Stdlib::Compat::Integer = Variant[Integer, Pattern[/^-?(?:(?:[1-9]\d*)|0)$/], Array[Variant[Integer, Pattern[/^-?(?:(?:[1-9]\d*)|0)$/]]]]
diff --git a/types/compat/ip_address.pp b/types/compat/ip_address.pp
new file mode 100644
index 0000000..bf4c4b4
--- /dev/null
+++ b/types/compat/ip_address.pp
@@ -0,0 +1 @@
+type Stdlib::Compat::Ip_address = Variant[Stdlib::Compat::Ipv4, Stdlib::Compat::Ipv6]
diff --git a/types/compat/ipv4.pp b/types/compat/ipv4.pp
new file mode 100644
index 0000000..a0ba0d6
--- /dev/null
+++ b/types/compat/ipv4.pp
@@ -0,0 +1,2 @@
+# Emulate the validate_ipv4_address and is_ipv4_address functions
+type Stdlib::Compat::Ipv4 = Pattern[/^((([0-9](?!\d)|[1-9][0-9](?!\d)|1[0-9]{2}(?!\d)|2[0-4][0-9](?!\d)|25[0-5](?!\d))[.]){3}([0-9](?!\d)|[1-9][0-9](?!\d)|1[0-9]{2}(?!\d)|2[0-4][0-9](?!\d)|25[0-5](?!\d)))(\/((([0-9](?!\d)|[1-9][0-9](?!\d)|1[0-9]{2}(?!\d)|2[0-4][0-9](?!\d)|25[0-5](?!\d))[.]){3}([0-9](?!\d)|[1-9][0-9](?!\d)|1[0-9]{2}(?!\d)|2[0-4][0-9](?!\d)|25[0-5](?!\d))|[0-9]+))?$/]
diff --git a/types/compat/ipv6.pp b/types/compat/ipv6.pp
new file mode 100644
index 0000000..18b148d
--- /dev/null
+++ b/types/compat/ipv6.pp
@@ -0,0 +1 @@
+type Stdlib::Compat::Ipv6 = Pattern[/^(?:(?:[\da-f]{1,4}:){7}[\da-f]{1,4}|((?:[\da-f]{1,4}:){6})(\d+)\.(\d+)\.(\d+)\.(\d+))$/]
diff --git a/types/compat/numeric.pp b/types/compat/numeric.pp
new file mode 100644
index 0000000..5bfc3d3
--- /dev/null
+++ b/types/compat/numeric.pp
@@ -0,0 +1,23 @@
+# Emulate the is_numeric and validate_numeric functions
+# The regex is what's currently used in is_numeric
+# validate_numeric also allows range checking, which cannot be mapped to the string parsing inside the function.
+# For full backwards compatibility, you will need to keep the validate_numeric call around to catch everything.
+# To keep your development moving forward, you can also add a deprecation warning using the Integer type:
+#
+# ```class example($value) { validate_numeric($value, 10, 0) }```
+#
+# would turn into
+#
+# ```
+# class example(Stdlib::Compat::Numeric $value) {
+# validate_numeric($value, 10, 0)
+# assert_type(Integer[0, 10], $value) |$expected, $actual| {
+# warning("The 'value' parameter for the 'ntp' class has type ${actual}, but should be ${expected}.")
+# }
+# }
+# ```
+#
+# > Note that you need to use Variant[Integer[0, 10], Float[0, 10]] if you want to match both integers and floating point numbers.
+#
+# This allows you to find all places where a consumers of your code call it with unexpected values.
+type Stdlib::Compat::Numeric = Variant[Numeric, Pattern[/^-?(?:(?:[1-9]\d*)|0)(?:\.\d+)?(?:[eE]-?\d+)?$/], Array[Variant[Numeric, Pattern[/^-?(?:(?:[1-9]\d*)|0)(?:\.\d+)?(?:[eE]-?\d+)?$/]]]]
diff --git a/types/compat/re.pp b/types/compat/re.pp
new file mode 100644
index 0000000..e4b5f30
--- /dev/null
+++ b/types/compat/re.pp
@@ -0,0 +1,3 @@
+# Emulate the validate_re function
+# validate_re(value, re) translates to Pattern[re], which is not directly mappable as a type alias, but can be specified as Pattern[re].
+# Therefore this needs to be translated directly.
diff --git a/types/compat/string.pp b/types/compat/string.pp
new file mode 100644
index 0000000..b06255d
--- /dev/null
+++ b/types/compat/string.pp
@@ -0,0 +1,2 @@
+# Emulate the is_string and validate_string functions
+type Stdlib::Compat::String = Optional[String]
diff --git a/types/httpsurl.pp b/types/httpsurl.pp
new file mode 100644
index 0000000..36fd30f
--- /dev/null
+++ b/types/httpsurl.pp
@@ -0,0 +1 @@
+type Stdlib::HTTPSUrl = Pattern[/^https:\/\//]
diff --git a/types/httpurl.pp b/types/httpurl.pp
new file mode 100644
index 0000000..0d93a95
--- /dev/null
+++ b/types/httpurl.pp
@@ -0,0 +1 @@
+type Stdlib::HTTPUrl = Pattern[/^https?:\/\//]
diff --git a/types/unixpath.pp b/types/unixpath.pp
new file mode 100644
index 0000000..76f2c17
--- /dev/null
+++ b/types/unixpath.pp
@@ -0,0 +1,2 @@
+# this regex rejects any path component that is a / or a NUL
+type Stdlib::Unixpath = Pattern[/^\/([^\/\0]+(\/)?)+$/]
diff --git a/types/windowspath.pp b/types/windowspath.pp
new file mode 100644
index 0000000..bc1ee9c
--- /dev/null
+++ b/types/windowspath.pp
@@ -0,0 +1 @@
+type Stdlib::Windowspath = Pattern[/^(([a-zA-Z]:[\\\/])|([\\\/][\\\/][^\\\/]+[\\\/][^\\\/]+)|([\\\/][\\\/]\?[\\\/][^\\\/]+))/]