Bug #12122
closedEnabling deep merge causes NoMethodError: undefined method `each_pair'
Description
Description of problem:
Enabling deep merge causes NoMethodError: undefined method `each_pair' with some kind of group-level overrides.
Steps to Reproduce:
1. Add https://forge.puppetlabs.com/stbenjam/hash_resources module to any puppet env;
2. Specify parameter type for smart class parameter "resources" as "hash";
3. Enable "Merge overrides";
4. On group level override "resources" value with the following:
keepalived::vrrp::instance:
VR_AP:
state: EQUAL
interface: <%= @host.primary_interface.identifier %>
virtual_router_id: 76
priority: 1
advert_int: 1
auth_type: PASS
auth_pass: KeeOpros
virtual_ipaddress:
- 10.8.36.76/23
5. Add host to that group;
6. On foreman host execute "/etc/puppet/node.rb hostname_with_overriden_resources"
Actual results:
Error retrieving node hostname: Net::HTTPPreconditionFailed Check Foreman's /var/log/foreman/production.log for more information.
production.log:
2015-10-09 14:14:46 [app] [I] Processing by HostsController#externalNodes as YML
2015-10-09 14:14:46 [app] [I] Parameters: {"name"=>"hostname"}
2015-10-09 14:14:47 [app] [W] Failed to generate external nodes for hostname
| NoMethodError: undefined method `each_pair' for #<String:0x007fbe6eeae5f0>
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/core_ext/hash/deep_merge.rb:15:in `deep_merge!'
| /usr/share/foreman/app/services/classification/base.rb:216:in `block in update_hash_matcher'
| /usr/share/foreman/app/services/classification/base.rb:211:in `each'
| /usr/share/foreman/app/services/classification/base.rb:211:in `update_hash_matcher'
| /usr/share/foreman/app/services/classification/base.rb:60:in `block in values_hash'
| /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/relation/delegation.rb:6:in `each'
| /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/relation/delegation.rb:6:in `each'
| /usr/share/foreman/app/services/classification/base.rb:39:in `values_hash'
| /usr/share/foreman/app/services/classification/class_param.rb:5:in `enc'
| /usr/share/foreman/app/models/host/managed.rb:833:in `lookup_keys_class_params'
| /usr/share/foreman/app/models/host/managed.rb:379:in `info'
| /opt/rh/ruby193/root/usr/share/gems/gems/katello-2.3.1/app/models/katello/concerns/host_managed_extensions.rb:37:in `info_with_katello'
| /usr/share/foreman/app/controllers/hosts_controller.rb:175:in `block (2 levels) in externalNodes'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_controller/metal/mime_responds.rb:196:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_controller/metal/mime_responds.rb:196:in `respond_to'
| /usr/share/foreman/app/controllers/hosts_controller.rb:173:in `externalNodes'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_controller/metal/implicit_render.rb:4:in `send_action'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/abstract_controller/base.rb:167:in `process_action'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_controller/metal/rendering.rb:10:in `process_action'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/abstract_controller/callbacks.rb:18:in `block in process_action'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:583:in `block (4 levels) in _run__3517729025394552365__process_action__3937467537153203590__callbacks'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:215:in `block in _conditional_callback_around_11924'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:326:in `around'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:310:in `_callback_around_2443'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:214:in `_conditional_callback_around_11924'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:560:in `block (3 levels) in _run__3517729025394552365__process_action__3937467537153203590__callbacks'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:215:in `block in _conditional_callback_around_11923'
| /usr/share/foreman/app/controllers/concerns/application_shared.rb:13:in `set_timezone'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:214:in `_conditional_callback_around_11923'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:559:in `block (2 levels) in _run__3517729025394552365__process_action__3937467537153203590__callbacks'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:215:in `block in _conditional_callback_around_11922'
| /usr/share/foreman/app/models/concerns/foreman/thread_session.rb:32:in `clear_thread'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:214:in `_conditional_callback_around_11922'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:437:in `block in _run__3517729025394552365__process_action__3937467537153203590__callbacks'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:215:in `block in _conditional_callback_around_11921'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:326:in `around'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:310:in `_callback_around_13'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:214:in `_conditional_callback_around_11921'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:403:in `_run__3517729025394552365__process_action__3937467537153203590__callbacks'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:405:in `__run_callback'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:385:in `_run_process_action_callbacks'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:81:in `run_callbacks'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/abstract_controller/callbacks.rb:17:in `process_action'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_controller/metal/rescue.rb:29:in `process_action'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_controller/metal/instrumentation.rb:30:in `block in process_action'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/notifications.rb:123:in `block in instrument'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/notifications.rb:123:in `instrument'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_controller/metal/instrumentation.rb:29:in `process_action'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_controller/metal/params_wrapper.rb:207:in `process_action'
| /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/railties/controller_runtime.rb:18:in `process_action'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/abstract_controller/base.rb:121:in `process'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/abstract_controller/rendering.rb:45:in `process'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_controller/metal.rb:203:in `dispatch'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_controller/metal/rack_delegation.rb:14:in `dispatch'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_controller/metal.rb:246:in `block in action'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/routing/route_set.rb:73:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/routing/route_set.rb:73:in `dispatch'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/routing/route_set.rb:36:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/journey-1.0.4/lib/journey/router.rb:68:in `block in call'
| /opt/rh/ruby193/root/usr/share/gems/gems/journey-1.0.4/lib/journey/router.rb:56:in `each'
| /opt/rh/ruby193/root/usr/share/gems/gems/journey-1.0.4/lib/journey/router.rb:56:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/routing/route_set.rb:600:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/static.rb:62:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/static.rb:62:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/apipie-rails-0.2.6/lib/apipie/extractor/recorder.rb:97:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/static.rb:62:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/static.rb:62:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/static.rb:62:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/static.rb:62:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/static.rb:62:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/apipie-rails-0.2.6/lib/apipie/middleware/checksum_in_headers.rb:27:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/etag.rb:23:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/conditionalget.rb:25:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/head.rb:14:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/params_parser.rb:21:in `call'
| /usr/share/foreman/lib/middleware/catch_json_parse_errors.rb:9:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/flash.rb:242:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/session/abstract/id.rb:205:in `context'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/session/abstract/id.rb:200:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/cookies.rb:339:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/query_cache.rb:64:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract/connection_pool.rb:473:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:405:in `_run__196417110406150970__call__2338207417472428176__callbacks'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:405:in `__run_callback'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:385:in `_run_call_callbacks'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:81:in `run_callbacks'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/callbacks.rb:27:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/remote_ip.rb:31:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/debug_exceptions.rb:16:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/show_exceptions.rb:56:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/railties-3.2.8/lib/rails/rack/logger.rb:26:in `call_app'
| /opt/rh/ruby193/root/usr/share/gems/gems/railties-3.2.8/lib/rails/rack/logger.rb:16:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/request_id.rb:22:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/methodoverride.rb:21:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/runtime.rb:17:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/activesupport-3.2.8/lib/active_support/cache/strategy/local_cache.rb:72:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/lock.rb:15:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/actionpack-3.2.8/lib/action_dispatch/middleware/static.rb:62:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-cache-1.2/lib/rack/cache/context.rb:136:in `forward'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-cache-1.2/lib/rack/cache/context.rb:245:in `fetch'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-cache-1.2/lib/rack/cache/context.rb:185:in `lookup'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-cache-1.2/lib/rack/cache/context.rb:66:in `call!'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-cache-1.2/lib/rack/cache/context.rb:51:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/railties-3.2.8/lib/rails/engine.rb:479:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/railties-3.2.8/lib/rails/application.rb:223:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/railties-3.2.8/lib/rails/railtie/configurable.rb:30:in `method_missing'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/builder.rb:134:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/urlmap.rb:64:in `block in call'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/urlmap.rb:49:in `each'
| /opt/rh/ruby193/root/usr/share/gems/gems/rack-1.4.1/lib/rack/urlmap.rb:49:in `call'
| /usr/share/gems/gems/passenger-4.0.18/lib/phusion_passenger/rack/thread_handler_extension.rb:77:in `process_request'
| /usr/share/gems/gems/passenger-4.0.18/lib/phusion_passenger/request_handler/thread_handler.rb:140:in `accept_and_process_next_request'
| /usr/share/gems/gems/passenger-4.0.18/lib/phusion_passenger/request_handler/thread_handler.rb:108:in `main_loop'
| /usr/share/gems/gems/passenger-4.0.18/lib/phusion_passenger/request_handler.rb:441:in `block (3 levels) in start_threads'
| /opt/rh/ruby193/root/usr/share/gems/gems/logging-1.8.2/lib/logging/diagnostic_context.rb:323:in `call'
| /opt/rh/ruby193/root/usr/share/gems/gems/logging-1.8.2/lib/logging/diagnostic_context.rb:323:in `block in create_with_logging_context'
2015-10-09 14:14:47 [app] [I] Rendered text template (0.0ms)
2015-10-09 14:14:47 [app] [I] Completed 412 Precondition Failed in 285ms (Views: 1.5ms | ActiveRecord: 49.8ms)
Expected results:
Correct node definition.
Additional info:
Seems to be important for me.
If I'll remove "interface: <%= @host.primary_interface.identifier %>" line from "override" value on group-level parameters than I can see that value turns to a string:
--- ! "keepalived::vrrp::instance:\r\n VR_AP:\r\n state: EQUAL\r\n virtual_router_id: 76\r\n priority: 1\r\n advert_int: 1\r\n auth_type: PASS\r\n auth_pass: KeeOpros\r\n virtual_ipaddress:\r\n - 10.8.36.76/23"
If I'll override this value from "Edit Puppet Class" page AND remove "interface: <%= @host.primary_interface.identifier %>" line then everything works as expected.
Package versions:
# rpm -qa | grep foreman ruby193-rubygem-puppetdb_foreman-0.1.2-1.el7.noarch ruby193-rubygem-foreman_gutterball-0.0.1-1.201507061443gitb9974c7.git.0.64e9626.el7.noarch ruby193-rubygem-foreman_templates-2.0.0-1.el7.noarch foreman-1.9.2-1.el7.noarch foreman-gce-1.9.2-1.el7.noarch foreman-postgresql-1.9.2-1.el7.noarch rubygem-hammer_cli_foreman_bootdisk-0.1.3-1.el7.noarch foreman-vmware-1.9.2-1.el7.noarch foreman-ec2-1.9.2-1.el7.noarch foreman-selinux-1.9.2-1.el7.noarch ruby193-rubygem-foreman_bootdisk-6.0.0-1.el7.noarch ruby193-rubygem-foreman-tasks-0.7.3-1.fm1_9.el7.noarch ruby193-rubygem-foreman_docker-1.4.1-1.fm1_9.el7.noarch ruby193-rubygem-foreman_setup-3.0.2-1.fm1_9.el7.noarch rubygem-hammer_cli_foreman-0.3.0-1.el7.noarch rubygem-hammer_cli_foreman_docker-0.0.3-2.el7.noarch ruby193-rubygem-foreman_remote_execution-0.0.4-1.fm1_9.el7.noarch foreman-compute-1.9.2-1.el7.noarch foreman-libvirt-1.9.2-1.el7.noarch ruby193-rubygem-foreman_default_hostgroup-3.0.0-1.el7.noarch foreman-proxy-1.9.2-1.el7.noarch rubygem-hammer_cli_foreman_tasks-0.0.7-1.el7.noarch ruby193-rubygem-foreman_hooks-0.3.8-1.el7.noarch ruby193-rubygem-foreman_discovery-4.0.0-1.fm1_9.el7.noarch foreman-debug-1.9.2-1.el7.noarch foreman-ovirt-1.9.2-1.el7.noarch
Updated by Dominic Cleal over 10 years ago
- Is duplicate of Feature #9949: deep merge broken when using facts in hash added
Updated by Dominic Cleal over 10 years ago
- Status changed from New to Duplicate
Thanks for the report. Deep merging won't work when combined with ERB (<%= .. %>) as you observed, and we're tracking support for this under ticket #9949.
Regarding the issue of the YAML becoming a string, we've been fixing this via host/group overrides in #11375 and for parameter default values in #12095.
Updated by Vladimir Stackov over 10 years ago
Sorry for duplicate and thanks for detailed clarification, I've tried to google error message on projects.theforeman.org with no luck.
Updated by Dominic Cleal over 10 years ago
No worries! Thanks for the detailed ticket anyway.