Hammer host update parameters overwriting previous updates

Problem:
“hammer host update --parameters” overwrites previous parameter overrides.

Expected outcome:
In Foreman 1.22, I could run multiple hammer host update parameter commands without overwriting previous updates. Each update should add an additional override rather than negating previous updates…

Foreman and Proxy versions:
1.23.0

Foreman and Proxy plugin versions:

0.16.2 foreman-tasks
0.8.1 foreman_chef
15.1.0 foreman_discovery
5.0.0 foreman-docker
1.8.2 foreman_remote_execution
3.13.0 katello

Other relevant data:

$ hammer host update --name servername.example.com --operatingsystem “CentOS 7” --parameters patch_week=“no-patch”,patch_day=“no-patch”,patch_time=“no-patch” --owner-type Usergroup --owner-id 1 --organization example
Host updated.

$ hammer host update --name servername.example.com --operatingsystem “CentOS 7” --parameters tla=syseng,node_type=db --owner-type Usergroup --owner-id 1 --organization example
Host updated.

logs

Is there anyone who can help with this?

Hi @tbrooks,

The hammer host update --parameters command is designed to set/reset host parameters. To create or append a parameter use hammer host set-parameter command.

Please, let me know whether this helps or not.

We had always used hammer host update --parameters in previous versions because I interpreted set-parameter as creating a new parameter rather than just changing the value of already set parameter. It was working correctly in Foreman 1.22. The behavior is odd in Foreman 1.23 because hammer host update --parameters now overwrites any prior changes, and returns the parameter back to the default.

I tried your suggestion, but after several experiments, I found that it only works for parameters that were already overriding the default global parameter. It does not work for any parameter that was not already overriding the default.

$ hammer host set-parameter --name 'tla' --parameter-type 'string' --value 'syseng' --host sysenga05a.a.example.us
Could not set host parameter:
  Internal Server Error: the server was unable to finish the request. This may be caused by unavailability of some required service, incorrect API call or a server-side bug. There may be more information in the server's logs.

$ hammer host set-parameter --name 'patch_time' --parameter-type 'string' --value '1100' --host sysenga05a.a.example.us
Could not set host parameter:
  Internal Server Error: the server was unable to finish the request. This may be caused by unavailability of some required service, incorrect API call or a server-side bug. There may be more information in the server's logs.

$ hammer host set-parameter --name 'patch_day' --parameter-type 'string' --value 'wednesday' --host sysenga05a.a.example.us
Could not set host parameter:
  Internal Server Error: the server was unable to finish the request. This may be caused by unavailability of some required service, incorrect API call or a server-side bug. There may be more information in the server's logs.

This is the only parameter that works with your method (and did not overwrite prior changes):

$ hammer host set-parameter --name 'node_type' --parameter-type 'string' --value 'db' --host sysenga05a.a.example.us
Host parameter updated
$ hammer host set-parameter --name 'node_type' --parameter-type 'string' --value 'app' --host sysenga05a.a.example.us
Host parameter updated

Logs for one parameter that works:

2019-10-29T11:31:17 [I|app|44680e83] Processing by Api::V2::ParametersController#index as JSON
2019-10-29T11:31:17 [I|app|44680e83]   Parameters: {"search"=>"name = \"node_type\"", "per_page"=>"1000", "page"=>"1", "apiv"=>"v2", "host_id"=>"76", "parameter"=>{}}
2019-10-29T11:31:18 [W|app|44680e83] Scoped order is ignored, it's forced to be batch order.
2019-10-29T11:31:18 [I|app|44680e83] Authorized user timbrooks(Tim Brooks)
2019-10-29T11:31:18 [I|app|44680e83]   Rendering api/v2/parameters/index.json.rabl within api/v2/layouts/index_layout
2019-10-29T11:31:18 [I|app|44680e83]   Rendered api/v2/parameters/index.json.rabl within api/v2/layouts/index_layout (7.2ms)
2019-10-29T11:31:18 [I|app|44680e83] Completed 200 OK in 1469ms (Views: 7.7ms | ActiveRecord: 31.2ms)
2019-10-29T11:31:18 [I|app|7f091bde] Started PUT "/api/hosts/76/parameters/1023" for 172.18.11.8 at 2019-10-29 11:31:18 -0500
2019-10-29T11:31:18 [I|app|7f091bde] Processing by Api::V2::ParametersController#update as JSON
2019-10-29T11:31:18 [I|app|7f091bde]   Parameters: {"parameter"=>{"value"=>"[FILTERED]", "parameter_type"=>"string", "hidden_value"=>"[FILTERED]"}, "apiv"=>"v2", "host_id"=>"76", "id"=>"1023"}
2019-10-29T11:31:19 [W|app|7f091bde] Scoped order is ignored, it's forced to be batch order.
2019-10-29T11:31:20 [I|app|7f091bde] Authorized user timbrooks(Tim Brooks)
2019-10-29T11:31:20 [I|aud|7f091bde] Parameter (1023) update event on value app, db
2019-10-29T11:31:20 [I|app|7f091bde]   Rendering api/v2/parameters/update.json.rabl
2019-10-29T11:31:20 [I|app|7f091bde]   Rendered api/v2/parameters/update.json.rabl (5.3ms)
2019-10-29T11:31:20 [I|app|7f091bde] Completed 200 OK in 1549ms (Views: 21.2ms | ActiveRecord: 78.2ms)

And logs for the failed update:

$ hammer host set-parameter --name 'patch_day' --parameter-type 'string' --value 'wednesday' --host sysenga05a.a.carfax.us

2019-10-29T11:40:59 [I|app|802f91aa] Started GET "/api/hosts/76/parameters?search=name+%3D+%22patch_day%22&per_page=1000&page=1" for 172.18.11.8 at 2019-10-29 11:40:59 -0500
2019-10-29T11:40:59 [I|app|802f91aa] Processing by Api::V2::ParametersController#index as JSON
2019-10-29T11:40:59 [I|app|802f91aa]   Parameters: {"search"=>"name = \"patch_day\"", "per_page"=>"1000", "page"=>"1", "apiv"=>"v2", "host_id"=>"76", "parameter"=>{}}
2019-10-29T11:41:00 [W|app|802f91aa] Scoped order is ignored, it's forced to be batch order.
2019-10-29T11:41:00 [I|app|802f91aa] Authorized user timbrooks(Tim Brooks)
2019-10-29T11:41:00 [I|app|802f91aa]   Rendering api/v2/parameters/index.json.rabl within api/v2/layouts/index_layout
2019-10-29T11:41:00 [I|app|802f91aa]   Rendered api/v2/parameters/index.json.rabl within api/v2/layouts/index_layout (1.8ms)
2019-10-29T11:41:00 [I|app|802f91aa] Completed 200 OK in 1328ms (Views: 3.6ms | ActiveRecord: 42.0ms)
2019-10-29T11:41:00 [I|app|19249c5d] Started POST "/api/hosts/76/parameters" for 172.18.11.8 at 2019-10-29 11:41:00 -0500
2019-10-29T11:41:00 [I|app|19249c5d] Processing by Api::V2::ParametersController#create as JSON
2019-10-29T11:41:00 [I|app|19249c5d]   Parameters: {"parameter"=>{"name"=>"patch_day", "value"=>"[FILTERED]", "parameter_type"=>"string", "hidden_value"=>"[FILTERED]"}, "apiv"=>"v2", "host_id"=>"76"}
2019-10-29T11:41:01 [W|app|19249c5d] Scoped order is ignored, it's forced to be batch order.
2019-10-29T11:41:02 [I|app|19249c5d] Authorized user timbrooks(Tim Brooks)
2019-10-29T11:41:02 [W|app|19249c5d] Action failed
ActiveModel::UnknownAttributeError: unknown attribute 'organization_id' for HostParameter.
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activemodel-5.2.1/lib/active_model/attribute_assignment.rb:53:in `_assign_attribute'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activemodel-5.2.1/lib/active_model/attribute_assignment.rb:44:in `block in _assign_attributes'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activemodel-5.2.1/lib/active_model/attribute_assignment.rb:43:in `each'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activemodel-5.2.1/lib/active_model/attribute_assignment.rb:43:in `_assign_attributes'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activerecord-5.2.1/lib/active_record/attribute_assignment.rb:23:in `_assign_attributes'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activemodel-5.2.1/lib/active_model/attribute_assignment.rb:35:in `assign_attributes'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activerecord-5.2.1/lib/active_record/core.rb:314:in `initialize'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activerecord-5.2.1/lib/active_record/inheritance.rb:66:in `new'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activerecord-5.2.1/lib/active_record/inheritance.rb:66:in `new'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activerecord-5.2.1/lib/active_record/reflection.rb:154:in `build_association'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activerecord-5.2.1/lib/active_record/associations/association.rb:276:in `build_record'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activerecord-5.2.1/lib/active_record/associations/collection_association.rb:106:in `build'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activerecord-5.2.1/lib/active_record/associations/collection_proxy.rb:319:in `build'
/usr/share/foreman/app/controllers/api/v2/parameters_controller.rb:86:in `create'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/abstract_controller/base.rb:194:in `process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal/rendering.rb:30:in `process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/abstract_controller/callbacks.rb:42:in `block in process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:109:in `block in run_callbacks'
/usr/share/foreman/app/controllers/api/v2/base_controller.rb:163:in `disable_json_root'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
/usr/share/foreman/app/controllers/concerns/foreman/controller/timezone.rb:10:in `set_timezone'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
/usr/share/foreman/app/models/concerns/foreman/thread_session.rb:32:in `clear_thread'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
/usr/share/foreman/app/controllers/concerns/foreman/controller/topbar_sweeper.rb:12:in `set_topbar_sweeper_controller'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
/opt/theforeman/tfm/root/usr/share/gems/gems/audited-4.7.1/lib/audited/sweeper.rb:14:in `around'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
/opt/theforeman/tfm/root/usr/share/gems/gems/audited-4.7.1/lib/audited/sweeper.rb:14:in `around'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:136:in `run_callbacks'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/abstract_controller/callbacks.rb:41:in `process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal/rescue.rb:22:in `process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal/instrumentation.rb:34:in `block in process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/notifications.rb:168:in `block in instrument'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/notifications/instrumenter.rb:23:in `instrument'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/notifications.rb:168:in `instrument'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal/instrumentation.rb:32:in `process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal/params_wrapper.rb:256:in `process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activerecord-5.2.1/lib/active_record/railties/controller_runtime.rb:24:in `process_action'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/abstract_controller/base.rb:134:in `process'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionview-5.2.1/lib/action_view/rendering.rb:32:in `process'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal.rb:191:in `dispatch'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_controller/metal.rb:252:in `dispatch'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/routing/route_set.rb:52:in `dispatch'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/routing/route_set.rb:34:in `serve'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/routing/mapper.rb:18:in `block in <class:Constraints>'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/routing/mapper.rb:48:in `serve'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/journey/router.rb:52:in `block in serve'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/journey/router.rb:35:in `each'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/journey/router.rb:35:in `serve'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/routing/route_set.rb:840:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/static.rb:127:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/static.rb:127:in `call'
/opt/theforeman/tfm/root/usr/share/gems/gems/apipie-rails-0.5.14/lib/apipie/static_dispatcher.rb:65:in `call'
/opt/theforeman/tfm/root/usr/share/gems/gems/apipie-rails-0.5.14/lib/apipie/extractor/recorder.rb:137:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/static.rb:127:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/static.rb:127:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/static.rb:127:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/static.rb:127:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/static.rb:127:in `call'
/usr/share/foreman/lib/foreman/middleware/telemetry.rb:10:in `call'
/opt/theforeman/tfm/root/usr/share/gems/gems/apipie-rails-0.5.14/lib/apipie/middleware/checksum_in_headers.rb:27:in `call'
/usr/share/foreman/lib/foreman/middleware/catch_json_parse_errors.rb:9:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/tempfile_reaper.rb:15:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/etag.rb:25:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/conditional_get.rb:38:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/head.rb:12:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/http/content_security_policy.rb:18:in `call'
/usr/share/foreman/lib/foreman/middleware/logging_context_session.rb:22:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/session/abstract/id.rb:232:in `context'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/session/abstract/id.rb:226:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/cookies.rb:670:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:98:in `run_callbacks'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/callbacks.rb:26:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/railties-5.2.1/lib/rails/rack/logger.rb:38:in `call_app'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/railties-5.2.1/lib/rails/rack/logger.rb:28:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/sprockets-rails-3.2.1/lib/sprockets/rails/quiet_assets.rb:13:in `call'
/usr/share/foreman/lib/foreman/middleware/logging_context_request.rb:11:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/request_id.rb:27:in `call'
/opt/theforeman/tfm/root/usr/share/gems/gems/katello-3.13.0/lib/katello/prevent_json_parsing.rb:12:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/method_override.rb:22:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/runtime.rb:22:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/activesupport-5.2.1/lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/executor.rb:14:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/actionpack-5.2.1/lib/action_dispatch/middleware/static.rb:127:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/sendfile.rb:111:in `call'
/opt/theforeman/tfm/root/usr/share/gems/gems/secure_headers-6.0.0/lib/secure_headers/middleware.rb:13:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/railties-5.2.1/lib/rails/engine.rb:524:in `call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/railties-5.2.1/lib/rails/railtie.rb:190:in `public_send'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/railties-5.2.1/lib/rails/railtie.rb:190:in `method_missing'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/urlmap.rb:68:in `block in call'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/urlmap.rb:53:in `each'
/opt/theforeman/tfm-ror52/root/usr/share/gems/gems/rack-2.0.6/lib/rack/urlmap.rb:53:in `call'
/usr/share/passenger/phusion_passenger/rack/thread_handler_extension.rb:74:in `process_request'
/usr/share/passenger/phusion_passenger/request_handler/thread_handler.rb:141:in `accept_and_process_next_request'
/usr/share/passenger/phusion_passenger/request_handler/thread_handler.rb:109:in `main_loop'
/usr/share/passenger/phusion_passenger/request_handler.rb:455:in `block (3 levels) in start_threads'
/opt/theforeman/tfm/root/usr/share/gems/gems/logging-2.2.2/lib/logging/diagnostic_context.rb:474:in `block in create_with_logging_context'

Thanks for great and detailed outputs! That helps a lot.

Unfortunatelly, there were changes in 1.23 that affected parameters creation from API. As you may see in logs for the failed update
Action failed ActiveModel::UnknownAttributeError: unknown attribute 'organization_id' for HostParameter there is problem on the server side, not hammer (since hammer uses API endpoints).

We are aware of this issue and it’s been solved already. The fix will be in 1.24 for sure, but I’m not sure if this will be cherry-picked to one of minor releases of 1.23. @tbrisker, could you give some related information or correct me if I’m wrong?

This is Bug #27740: Cannot set parameter for hostgroup - Foreman which will be in 1.23.1 (and can also be patched manually if needed - it’s a one line change that can be found at https://github.com/theforeman/foreman/commit/4bcb3a52d117daef133dc0f8640e0495e6b674ba#diff-b4f92b4e361ffab4fbb91c68eb3f77bbR233)

1 Like

Wonderful, I made the change to app/controllers/api/base_controller.rb, and now hammer host set-parameter is working correctly.

Thanks for all the help!

1 Like