Skip to content

Create Method Clobbers Multiple List Values #33

@harlanbarnes

Description

@harlanbarnes

It appears that the create method will collapse lists/arrays and only keep the last value. For example, I was trying to add a host to multiple hostgroups:

hostid = zabbix.hosts.create_or_update(
      :host => host.fqdn,
      :interfaces => interfaces,
      :groups => [ {:group_id => 1}, {:group_id =>2} ]
      )

With debug turned on, I could see the call create with multiple group hashes in the params:

[DEBUG] Call create with parametrs: {:host=>"foo", :interfaces=>[{:type=>1, :main=>1, :ip=>"192.168.1.1", :dns=>"foo", :port=>10050, :useip=>0}], :groups=>[{:groupid=>"1"}, {:groupid=>"2"}]}

but then I would see the request being created with just the second id group id:

[DEBUG] Send request: {"method":"host.create","params":[{"host":foo","interfaces":[{"type":1,"main":1,"ip":"192.168.1.1","dns":"foo","port":10050,"useip":0}],"status":0,"available":1,"groups":[{"groupid":"2"}], "auth":"......................", "id":69893, "jsonrpc":"2.0"}

I think I tracked it down to the merge_params in basic_func.rb (i'm using 2.0, but I presume 1.8 is like this too). I think this line is what does it ...

JSON.parse(result.gsub('},{', ','))

If I understand, the intent here is to let JSON do the merging of the default and given params into a single JSON doc and then reparse it. But it picks up and does the substiution on lists of hashes for things like groups, templates, macros, etc. ... and leaves only one in the list.

I know this isn't a proper PR, but this seems to work for me (and it gets JSON out of the picture too ... might be a little faster.)

    def stringify_keys(obj)
      return obj.inject({}){|memo,(k,v)| memo[k.to_s] =  stringify_keys(v); memo} if obj.is_a? Hash
      return obj.inject([]){|memo,v    | memo         << stringify_keys(v); memo} if obj.is_a? Array
      obj
    end

    def merge_params(params)
      stringify_keys(default_options.merge(params))
    end

I presume you were also using the JSON conversion for converting all the symbols to strings too. If I'm wrong about the reasoning behind the JSON maneuvers, then this works too:

    def merge_params(params)
      new_params = default_options.merge(params)
      JSON.parse(JSON.generate(new_params).to_s)
    end

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions