Skip to content

Conversation

@rahmnstein
Copy link

Fix inventory_mode update issue by correcting pointer assignment in prepHosts

Description

When updating a host's inventory_mode from "manual" to "automatic" using Terraform, the change was not taking effect. Despite a successful terraform apply, subsequent runs showed the value reverting back to "manual". Additionally, Terraform debug logs revealed that the inventory_mode field was missing from the POST request sent to the Zabbix API. For example, before the fix, the API request looked like this:

{
  "jsonrpc": "2.0",
  "method": "host.update",
  "params": [{
    "hostid": "10632",
    "host": "testzabbixsrv70",
    "available": "0",
    "error": "",
    "name": "testzabbixsrv70",
    "status": "0",
    "inventory": {"location_lat": "56.95387", "location_lon": "24.22067"},
    "groups": [{"groupid": "4"}],
    "interfaces": [{
      "interfaceid": "32",
      "dns": "",
      "ip": "10.200.183.122",
      "main": "1",
      "port": "10050",
      "type": "1",
      "useip": "1"
    }],
    "templates": [{"templateid": "10001"}, {"templateid": "10047"}],
    "proxy_hostid": "0"
  }],
  "auth": "afc643f7e88ea4d91de499d935ec3c82",
  "id": 3
}

A warning was also logged:

WARN: Provider produced an unexpected new value for inventory_mode: was "automatic", but now "manual".


Root Cause

The root cause was identified in the prepHosts function in host.go. The function is meant to prepare host data before sending it to the API by assigning the pointer for RawInventoryMode. However, the assignment was performed on a temporary variable (h), rather than directly on the slice element, resulting in the change not being reflected in the data sent to the API.

Original Code:

func prepHosts(hosts Hosts) {
    for i := 0; i < len(hosts); i++ {
        h := hosts[i]
        for j := 0; j < len(h.Interfaces); j++ {
            in := h.Interfaces[j]
            if in.Details == nil {
                continue
            }
            asB, _ := json.Marshal(in.Details)
            hosts[i].Interfaces[j].RawDetails = json.RawMessage(asB)
        }
        if h.Inventory != nil {
            asB, _ := json.Marshal(h.Inventory)
            hosts[i].RawInventory = json.RawMessage(asB)
        }
        invMode := h.InventoryMode
        h.RawInventoryMode = &invMode
    }
}

Fix

The fix updates the assignment so that it writes directly into the slice element instead of the temporary variable:

Updated Code:

func prepHosts(hosts Hosts) {
    for i := 0; i < len(hosts); i++ {
        h := hosts[i]
        for j := 0; j < len(h.Interfaces); j++ {
            in := h.Interfaces[j]
            if in.Details == nil {
                continue
            }
            asB, _ := json.Marshal(in.Details)
            hosts[i].Interfaces[j].RawDetails = json.RawMessage(asB)
        }
        if h.Inventory != nil {
            asB, _ := json.Marshal(h.Inventory)
            hosts[i].RawInventory = json.RawMessage(asB)
        }
        invMode := h.InventoryMode
        hosts[i].RawInventoryMode = &invMode
    }
}

Verification

After applying these changes:

  • Running terraform apply now sends a POST request that includes "inventory_mode": "1" (representing "automatic") as expected:

    {
      "jsonrpc": "2.0",
      "method": "host.update",
      "params": [{
        "hostid": "10632",
        "host": "testzabbixsrv70",
        "available": "0",
        "error": "",
        "name": "testzabbixsrv70",
        "status": "0",
        "inventory": {"location_lat": "56.95387", "location_lon": "24.22067"},
        "inventory_mode": "1",
        "groups": [{"groupid": "4"}],
        "interfaces": [{
          "interfaceid": "32",
          "dns": "",
          "ip": "10.200.183.122",
          "main": "1",
          "port": "10050",
          "type": "1",
          "useip": "1"
        }],
        "templates": [{"templateid": "10001"}, {"templateid": "10047"}],
        "proxy_hostid": "0"
      }],
      "auth": "1b7b82ad7d3818ebbd326b9cd49b8410",
      "id": 3
    }
    
  • The warning about the unexpected new value for inventory_mode no longer appears.

  • Subsequent terraform apply runs confirm that the infrastructure state now matches the configuration with no unintended changes.

Please review these changes and let me know if you have any questions or need further details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant