diff --git a/acceptance/tests/apply/hashes/should_not_reassign.rb b/acceptance/tests/apply/hashes/should_not_reassign.rb index 115e54b2b..885939ffe 100755 --- a/acceptance/tests/apply/hashes/should_not_reassign.rb +++ b/acceptance/tests/apply/hashes/should_not_reassign.rb @@ -1,19 +1,12 @@ test_name "hash reassignment should fail" manifest = %q{ $my_hash = {'one' => '1', 'two' => '2' } $my_hash['one']='1.5' } agents.each do |host| - parser = on(host, puppet('agent --configprint parser')).stdout.chomp apply_manifest_on(host, manifest, :acceptable_exit_codes => [1]) do - expected_error_message = - case parser - when 'future' - "Illegal attempt to assign via [index/key]. Not an assignable reference" - else - "Assigning to the hash 'my_hash' with an existing key 'one'" - end + expected_error_message = "Illegal attempt to assign via [index/key]. Not an assignable reference" fail_test("didn't find the failure") unless stderr.include?(expected_error_message) end end diff --git a/acceptance/tests/environment/dynamic.rb b/acceptance/tests/environment/dynamic.rb index b9eaae5c4..9d5a1d5f8 100644 --- a/acceptance/tests/environment/dynamic.rb +++ b/acceptance/tests/environment/dynamic.rb @@ -1,130 +1,127 @@ test_name "dynamic environments" require 'puppet/acceptance/environment_utils' extend Puppet::Acceptance::EnvironmentUtils require 'puppet/acceptance/classifier_utils' extend Puppet::Acceptance::ClassifierUtils classify_nodes_as_agent_specified_if_classifer_present step "setup environments" stub_forge_on(master) testdir = create_tmpdir_for_user master, "confdir" puppet_conf_backup_dir = create_tmpdir_for_user(master, "puppet-conf-backup-dir") apply_manifest_on(master, environment_manifest(testdir), :catch_failures => true) results = {} review = {} #################### step "[ Run Tests ]" existing_dynamic_scenario = "Test a specific, existing dynamic environment configuration" step existing_dynamic_scenario master_opts = { 'main' => { 'environmentpath' => '', 'manifest' => '$confdir/dynamic/$environment/manifests', 'modulepath' => '$confdir/dynamic/$environment/modules', 'config_version' => '$confdir/static-version.sh', } } if master.is_pe? master_opts['main']['modulepath'] << ":#{master['sitemoduledir']}" end results[existing_dynamic_scenario] = use_an_environment("testing", "dynamic testing", master_opts, testdir, puppet_conf_backup_dir) default_environment_scenario = "Test behavior of default environment" step default_environment_scenario results[default_environment_scenario] = use_an_environment(nil, "default environment", master_opts, testdir, puppet_conf_backup_dir) non_existent_environment_scenario = "Test for an environment that does not exist" step non_existent_environment_scenario results[non_existent_environment_scenario] = use_an_environment("doesnotexist", "non existent environment", master_opts, testdir, puppet_conf_backup_dir) ######################################## step "[ Report on Environment Results ]" confdir = master.puppet['confdir'] step "Reviewing: #{existing_dynamic_scenario}" review[existing_dynamic_scenario] = review_results(results[existing_dynamic_scenario], :puppet_config => { :exit_code => 0, :matches => [%r{manifest.*#{confdir}/dynamic/testing/manifests$}, %r{modulepath.*#{confdir}/dynamic/testing/modules(?::#{master['sitemoduledir']})?$}, %r{config_version.*#{confdir}/static-version.sh$}] }, :puppet_module_install => { :exit_code => 0, :matches => [%r{Preparing to install into #{confdir}/dynamic/testing/modules}, %r{pmtacceptance-nginx}], }, :puppet_module_uninstall => { :exit_code => 0, :matches => [%r{Removed.*pmtacceptance-nginx.*from #{confdir}/dynamic/testing/modules}], }, :puppet_apply => { :exit_code => 0, :matches => [%r{include dynamic testing environment testing_mod}], }, :puppet_agent => { :exit_code => 2, :matches => [%r{Applying configuration version 'static'}, %r{in dynamic testing environment site.pp}, %r{include dynamic testing environment testing_mod}], } ) step "Reviewing: #{default_environment_scenario}" default_expectations = lambda do |env| { :puppet_config => { :exit_code => 0, :matches => [%r{manifest.*#{confdir}/dynamic/#{env}/manifests$}, %r{modulepath.*#{confdir}/dynamic/#{env}/modules(?::#{master['sitemoduledir']})?$}, %r{^config_version.*#{confdir}/static-version.sh$}] }, :puppet_module_install => { :exit_code => 0, :matches => [%r{Preparing to install into #{confdir}/dynamic/#{env}/modules}, %r{pmtacceptance-nginx}], }, :puppet_module_uninstall => { :exit_code => 0, :matches => [%r{Removed.*pmtacceptance-nginx.*from #{confdir}/dynamic/#{env}/modules}], }, :puppet_apply => { :exit_code => 1, - :matches => [ENV['PARSER'] == 'future' ? - %r{Error:.*Could not find class ::testing_mod} : - %r{Error:.*Could not find class testing_mod} - ], + :matches => [%r{Error:.*Could not find class ::testing_mod}], }, :puppet_agent => { :exit_code => 0, :matches => [%r{Applying configuration version 'static'}], :does_not_match => [%r{in default environment site.pp}, %r{include default environment testing_mod}, %r{Notice: include}], }, } end review[default_environment_scenario] = review_results( results[default_environment_scenario], default_expectations.call('production') ) step "Reviewing: #{non_existent_environment_scenario}" review[non_existent_environment_scenario] = review_results( results[non_existent_environment_scenario], default_expectations.call('doesnotexist') ) ######################### step "[ Assert Success ]" assert_review(review) diff --git a/acceptance/tests/loader/func4x_loadable_from_modules.rb b/acceptance/tests/loader/func4x_loadable_from_modules.rb index 60414d4b7..c59f92764 100644 --- a/acceptance/tests/loader/func4x_loadable_from_modules.rb +++ b/acceptance/tests/loader/func4x_loadable_from_modules.rb @@ -1,83 +1,83 @@ test_name "Exercise a module with 4x function and 4x system function" # Purpose: # Test that a packed puppet can call a 4x system function, and that a 4x function in # a module can be called. # # Method: # * Manually construct a very simple module with a manifest that creates a file. # * The file has content that depends on logic that calls both a system function (reduce), and # a function supplied in the module (helloworld::mul10). # * The module is manually constructed to allow the test to also run on Windows where the module tool # is not supported. # * The module is included by calling 'include' from 'puppet apply'. # * Puppet apply is executed to generate the file with the content. # * The generated contents is asserted. # TODO: The test can be improved by adding yet another module that calls the function in helloworld. # TODO: The test can be improved to also test loading of a non namespaced function require 'puppet/acceptance/temp_file_utils' extend Puppet::Acceptance::TempFileUtils initialize_temp_dirs agents.each do |agent| # The modulepath to use in environment 'dev' envs_path = get_test_file_path(agent, 'environments') dev_modulepath = get_test_file_path(agent, 'environments/dev/modules') target_path = get_test_file_path(agent, 'output') mkdirs agent, target_path # make sure that we use the modulepath from the dev environment puppetconf = get_test_file_path(agent, 'puppet.conf') user = agent.puppet['user'] group = agent.puppet['group'] # Setting user/group ensures that when puppet apply's Configurer use()'s the # settings, that it doesn't default to owning them as root, which can have an # impact on following tests. on agent, puppet("config", "set", "user", user, "--section", "main", "--config", puppetconf) on agent, puppet("config", "set", "group", group, "--section", "main", "--config", puppetconf) on agent, puppet("config", "set", "environment", "dev", "--section", "user", "--config", puppetconf) on agent, puppet("config", "set", "environmentpath", envs_path, "--section", "main", "--config", puppetconf) # Where the functions in the written modules should go helloworld_functions = 'helloworld/lib/puppet/functions/helloworld' # Clean out the module that will be written to ensure no interference from a previous run on agent, "rm -rf #{File.join(dev_modulepath, 'helloworld')}" mkdirs agent, File.join(dev_modulepath, helloworld_functions) # Write a module # Write the function helloworld::mul10, that multiplies its argument by 10 create_remote_file(agent, File.join(dev_modulepath, helloworld_functions, "mul10.rb"), <<'SOURCE') Puppet::Functions.create_function(:'helloworld::mul10') do def mul10(x) x * 10 end end SOURCE # Write a manifest that calls a 4x function (reduce), and calls a function defined in the module # (helloworld::mul10). # mkdirs agent, File.join(dev_modulepath, "helloworld", "manifests") create_remote_file(agent, File.join(dev_modulepath, "helloworld", "manifests", "init.pp"), < 'file', mode => '0666', content => [1,2,3].reduce("Generated") |$memo, $n| { "${memo}, ${n} => ${helloworld::mul10($n)}" } } } SOURCE # Run apply to generate the file with the output - on agent, puppet('apply', '--parser', 'future', '-e', "'include helloworld'", '--config', puppetconf) + on agent, puppet('apply', '-e', "'include helloworld'", '--config', puppetconf) # Assert that the file was written with the generated content on(agent, "cat #{File.join(target_path, 'result.txt')}") do assert_match(/^Generated, 1 => 10, 2 => 20, 3 => 30$/, stdout, "Generated the wrong content") end end diff --git a/lib/puppet/functions/each.rb b/lib/puppet/functions/each.rb index 1b9ac937c..5a5c39dac 100644 --- a/lib/puppet/functions/each.rb +++ b/lib/puppet/functions/each.rb @@ -1,111 +1,109 @@ # Applies a parameterized block to each element in a sequence of selected entries from the first # argument and returns the first argument. # # This function takes two mandatory arguments: the first should be an Array or a Hash or something that is # of enumerable type (integer, Integer range, or String), and the second # a parameterized block as produced by the puppet syntax: # # $a.each |$x| { ... } # each($a) |$x| { ... } # # When the first argument is an Array (or of enumerable type other than Hash), the parameterized block # should define one or two block parameters. # For each application of the block, the next element from the array is selected, and it is passed to # the block if the block has one parameter. If the block has two parameters, the first is the elements # index, and the second the value. The index starts from 0. # # $a.each |$index, $value| { ... } # each($a) |$index, $value| { ... } # # When the first argument is a Hash, the parameterized block should define one or two parameters. # When one parameter is defined, the iteration is performed with each entry as an array of `[key, value]`, # and when two parameters are defined the iteration is performed with key and value. # # $a.each |$entry| { ..."key ${$entry[0]}, value ${$entry[1]}" } # $a.each |$key, $value| { ..."key ${key}, value ${value}" } # # @example using each # # [1,2,3].each |$val| { ... } # 1, 2, 3 # [5,6,7].each |$index, $val| { ... } # (0, 5), (1, 6), (2, 7) # {a=>1, b=>2, c=>3}].each |$val| { ... } # ['a', 1], ['b', 2], ['c', 3] # {a=>1, b=>2, c=>3}.each |$key, $val| { ... } # ('a', 1), ('b', 2), ('c', 3) # Integer[ 10, 20 ].each |$index, $value| { ... } # (0, 10), (1, 11) ... # "hello".each |$char| { ... } # 'h', 'e', 'l', 'l', 'o' # 3.each |$number| { ... } # 0, 1, 2 # -# @since 3.2 for Array and Hash -# @since 3.5 for other enumerables -# @note requires `parser = future` +# @since 4.0.0 # Puppet::Functions.create_function(:each) do dispatch :foreach_Hash_2 do param 'Hash[Any, Any]', :hash required_block_param 'Callable[2,2]', :block end dispatch :foreach_Hash_1 do param 'Hash[Any, Any]', :hash required_block_param 'Callable[1,1]', :block end dispatch :foreach_Enumerable_2 do param 'Any', :enumerable required_block_param 'Callable[2,2]', :block end dispatch :foreach_Enumerable_1 do param 'Any', :enumerable required_block_param 'Callable[1,1]', :block end def foreach_Hash_1(hash, pblock) enumerator = hash.each_pair hash.size.times do pblock.call(nil, enumerator.next) end # produces the receiver hash end def foreach_Hash_2(hash, pblock) enumerator = hash.each_pair hash.size.times do pblock.call(nil, *enumerator.next) end # produces the receiver hash end def foreach_Enumerable_1(enumerable, pblock) enum = asserted_enumerable(enumerable) begin loop { pblock.call(nil, enum.next) } rescue StopIteration end # produces the receiver enumerable end def foreach_Enumerable_2(enumerable, pblock) enum = asserted_enumerable(enumerable) index = 0 begin loop do pblock.call(nil, index, enum.next) index += 1 end rescue StopIteration end # produces the receiver enumerable end def asserted_enumerable(obj) unless enum = Puppet::Pops::Types::Enumeration.enumerator(obj) raise ArgumentError, ("#{self.class.name}(): wrong argument type (#{obj.class}; must be something enumerable.") end enum end end diff --git a/lib/puppet/functions/epp.rb b/lib/puppet/functions/epp.rb index baa0c1bed..35ff0286c 100644 --- a/lib/puppet/functions/epp.rb +++ b/lib/puppet/functions/epp.rb @@ -1,54 +1,54 @@ # Evaluates an Embedded Puppet Template (EPP) file and returns the rendered text result as a String. # # The first argument to this function should be a `/