Dataplaneapi PUT to replace backend is not actually updating the backend

Hi.

Firstly, I’m a newbie here and a newbie to haproxy. I’ve searched the forum and googled loads but can’d find an answer to my problem, so really sorry if this is a FAQ.

I’m using the dataplaneapi to update servers on a backend, but while the PUT request to replace the backend comes back with a success response, it doesn’t seem to actually change anything.

This is with these software versions running on Debian 12:

  • HAProxy version 2.6.12-1+deb12u1 2023/12/16
  • dataplaneapi version 3.0.2

FYI, below I’ve prefixed stuff with “RX:” and “TX:” for clarity, and pretty printed the JSON for readability (which is why it doesn’t match any content length headers).

I’m not using a transaction_id but instead using version=XX and force_reload=1. I presume by doing this that my updates should be effective immediately and don’t require a subsequent commit (because the docs told me that commit needed a transaction_id and also that transaction_id could not be used with version).

In this example, I’m GETting the backend “smsapi”, then using PUT to replace it, and then GETting it again. I would have expect the second GET to return the updated data, but it does not. It returns the original data.

Further to this, the haproxy.cfg content doesn’t get changed apart from the version number, which automatically updates to match what the API returns.

IP addresses anonymised here, but are real in the actual data.

So first, the initial GET:

GET /v3/services/haproxy/configuration/backends/smsapi?full_section=true
RX: HTTP/1.1 200 OK
RX: Configuration-Version: 92
RX: Content-Type: application/json
RX: Vary: Origin
RX: Date: Fri, 18 Oct 2024 17:47:03 GMT
RX: Content-Length: 386
RX: 
RX: 
RX: {
RX:     "balance": {
RX:         "algorithm": "roundrobin"
RX:     },
RX:     "from": "smsapi",
RX:     "mode": "http",
RX:     "name": "smsapi",
RX:     "server_timeout": 300000,
RX:     "log_target_list": [
RX:         {
RX:             "address": "127.0.0.1",
RX:             "facility": "local1",
RX:             "level": "info"
RX:         }
RX:     ],
RX:     "servers": {
RX:         "smsapi-lon1a": {
RX:             "check": "enabled",
RX:             "address": "xxx.xxx.47.143",
RX:             "name": "smsapi-lon1a",
RX:             "port": 80
RX:         },
RX:         "smsapi-lon1b": {
RX:             "check": "enabled",
RX:             "address": "xxx.xxx.47.144",
RX:             "name": "smsapi-lon1b",
RX:             "port": 80
RX:         }
RX:     }
RX: }

Now a PUT to change the servers - request (TX) then response (RX):

PUT /v3/services/haproxy/configuration/backends/smsapi?version=92&force_reload=1
TX:{
TX:    "balance": {
TX:        "algorithm": "roundrobin"
TX:    },
TX:    "from": "smsapi",
TX:    "mode": "http",
TX:    "name": "smsapi",
TX:    "server_timeout": 300000,
TX:    "log_target_list": [
TX:        {
TX:            "address": "127.0.0.1",
TX:            "facility": "local1",
TX:            "level": "info"
TX:        }
TX:    ],
TX:    "servers": {
TX:        "smsapi-lon1a": {
TX:            "name": "smsapi-lon1a",
TX:            "port": 80,
TX:            "check": "enabled",
TX:            "address": "xxx.xxx.47.143"
TX:        },
TX:        "smsapi-lon1b": {
TX:            "name": "smsapi-lon1b",
TX:            "port": 80,
TX:            "check": "enabled",
TX:            "address": "xxx.xxx.47.144"
TX:        },
TX:        "smsapi-man1a": {
TX:            "name": "smsapi-man1a",
TX:            "port": 80,
TX:            "check": "enabled",
TX:            "address": "xxx.xxx.41.143"
TX:        }
TX:    }
TX:}

RX: HTTP/1.1 200 OK
RX: Configuration-Version: 93
RX: Content-Type: application/json
RX: Vary: Origin
RX: Date: Fri, 18 Oct 2024 17:47:04 GMT
RX: Content-Length: 479
RX: 
RX: 
RX: {
RX:     "balance": {
RX:         "algorithm": "roundrobin"
RX:     },
RX:     "from": "smsapi",
RX:     "mode": "http",
RX:     "name": "smsapi",
RX:     "server_timeout": 300000,
RX:     "log_target_list": [
RX:         {
RX:             "address": "127.0.0.1",
RX:             "facility": "local1",
RX:             "level": "info"
RX:         }
RX:     ],
RX:     "servers": {
RX:         "smsapi-lon1a": {
RX:             "check": "enabled",
RX:             "address": "xxx.xxx.47.143",
RX:             "name": "smsapi-lon1a",
RX:             "port": 80
RX:         },
RX:         "smsapi-lon1b": {
RX:             "check": "enabled",
RX:             "address": "xxx.xxx.47.144",
RX:             "name": "smsapi-lon1b",
RX:             "port": 80
RX:         },
RX:         "smsapi-man1a": {
RX:             "check": "enabled",
RX:             "address": "xxx.xxx.41.143",
RX:             "name": "smsapi-man1a",
RX:             "port": 80
RX:         }
RX:     }
RX: }

Then another GET to re-fetch after the PUT (at which point I was expecting to get the same results as the PUT’s return payload) but no, it shows the servers list unchanged:

GET /v3/services/haproxy/configuration/backends/smsapi?full_section=true
RX: HTTP/1.1 200 OK
RX: Configuration-Version: 93
RX: Content-Type: application/json
RX: Vary: Origin
RX: Date: Fri, 18 Oct 2024 17:47:04 GMT
RX: Content-Length: 386
RX: 
RX: 
RX: {
RX:     "balance": {
RX:         "algorithm": "roundrobin"
RX:     },
RX:     "from": "smsapi",
RX:     "mode": "http",
RX:     "name": "smsapi",
RX:     "server_timeout": 300000,
RX:     "log_target_list": [
RX:         {
RX:             "address": "127.0.0.1",
RX:             "facility": "local1",
RX:             "level": "info"
RX:         }
RX:     ],
RX:     "servers": {
RX:         "smsapi-lon1a": {
RX:             "check": "enabled",
RX:             "address": "xxx.xxx.47.143",
RX:             "name": "smsapi-lon1a",
RX:             "port": 80
RX:         },
RX:         "smsapi-lon1b": {
RX:             "check": "enabled",
RX:             "address": "xxx.xxx.47.144",
RX:             "name": "smsapi-lon1b",
RX:             "port": 80
RX:         }
RX:     }
RX: }

The haproxy.cfg file, at the end, has these lines at the top:

# _md5hash=a797082c51cbf4aa96586e306399d145
# _version=93
# Dataplaneapi managed File
# changing file directly can cause a conflict if dataplaneapi is running

Prior to the PUT, _version was 92, as you would expect.

Is there anything I’m doing obviously wrong?

Cheers,
Kingsley.