Page MenuHomeVyOS Platform

HTTPS API endpoint to check if an empty config exists
Resolved (N/A)PublicFEATURE REQUEST

Description

Currently there is no good way to check if an empty config exists without also retrieving the parent config node.

My use-case is that Terraform providers should not allow creation of resources that already exists, but instead ask for the resource to be imported.
This means that I must check for existing config before going along with the creation, and as you can guess this quickly becomes cumbersome when factoring in configs that do not have any "sub-configs".

Here we can see that the NTP servers do not contain any configs, but they themselves are configured:

$ curl -v -k --location --request POST "https://$VYOS_HOST/retrieve" --form key="$VYOS_KEY" --form data='{"op":"showConfig","path": ["service","ntp","server"]}' 2> >(grep "HTTP/1.1" 1>&2) | jq
> POST /retrieve HTTP/1.1
< HTTP/1.1 200 OK
{
  "success": true,
  "data": {
    "server": {
      "time1.vyos.net": {},
      "time2.vyos.net": {},
      "time3.vyos.net": {}
    }
  },
  "error": null
}

This means that when using the API to check if the server is configured we will get a false negative, indicating that it is not even though it is:

$ curl -v -k --location --request POST "https://$VYOS_HOST/retrieve" --form key="$VYOS_KEY" --form data='{"op":"showConfig","path": ["service","ntp","server","time1.vyos.net"]}' 2> >(grep "HTTP/1.1" 1>&2) | jq
> POST /retrieve HTTP/1.1
< HTTP/1.1 400 Bad Request
{
  "success": false,
  "error": "Configuration under specified path is empty\n",
  "data": null
}

The same issue persists with returnValues operation:

$ curl -v -k --location --request POST "https://$VYOS_HOST/retrieve" --form key="$VYOS_KEY" --form data='{"op":"returnValues","path": ["service","ntp","server","time1.vyos.net"]}' 2> >(grep "HTTP/1.1" 1>&2) | jq
> POST /retrieve HTTP/1.1
< HTTP/1.1 200 OK
{
  "success": true,
  "data": [],
  "error": null
}

The returnValues also indicates the same level of success ignoring not only if there is anything to return, but also if the config path is even legal. This means we can not depend on it either to check if the config exists:

$ curl -v -k --location --request POST "https://$VYOS_HOST/retrieve" --form key="$VYOS_KEY" --form data='{"op":"returnValues","path": ["FAKE-CONFIG","FAKE-SERVER"]}' 2> >(grep "HTTP/1.1" 1>&2) | jq
> POST /retrieve HTTP/1.1
< HTTP/1.1 200 OK
{
  "success": true,
  "data": [],
  "error": null
}

I do not know if it would be safe to change the API operation showConfig to return the empty config and a success when it is there, as that might be a regression in behavior if some users rely on that behavior for their tooling.

As I see it there are 3 options that seem reasonable to improve the situation:

  1. Add a new endpoint for the API, my suggestion: /has
  2. Add a new operation to the /retrieve endpoint, my suggestion: hasConfig
  3. Change the returnValues operation to include an error when there truly is no data to return

I feel the best option is to add a new operation to the /retrieve endpoint as this is a config retrieval feature, and no convoluted mangling of concerns have to be pushed into the returnValues operation.

The response could be something as simple as:

Success:

$ curl -v -k --location --request POST "https://$VYOS_HOST/retrieve" --form key="$VYOS_KEY" --form data='{"op":"hasConfig","path": ["service","ntp","server","time1.vyos.net"]}' 2> >(grep "HTTP/1.1" 1>&2) | jq
> POST /retrieve HTTP/1.1
< HTTP/1.1 200 OK
{
  "success": true,
  "data": [],
  "error": null
}

Failure:

$ curl -v -k --location --request POST "https://$VYOS_HOST/retrieve" --form key="$VYOS_KEY" --form data='{"op":"hasConfig","path": ["service","ntp","server","FAKE-SERVER"]}' 2> >(grep "HTTP/1.1" 1>&2) | jq
> POST /retrieve HTTP/1.1
< HTTP/1.1 400 Bad Request
{
  "success": false,
  "data": null,
  "error": "Configuration under specified path is empty\n"
}

This would be very reminiscent of the showConfig operation, except we now have the option to check for empty but existing configs.

As a bonus there is space in the data field if some extra functionality would be added in the future. Some silly ideas could be the config comment or if it is saved to disk/config file or it could be used as a "catch all" to return any config warnings or errors no matter what path you ask for.

Details

Difficulty level
Unknown (require assessment)
Version
-
Why the issue appeared?
Will be filled on close
Is it a breaking change?
Perfectly compatible
Issue type
Improvement (missing useful functionality)

Event Timeline

penetal updated the task description. (Show Details)
Viacheslav triaged this task as Normal priority.Mar 18 2024, 9:10 AM

@penetal does the operation 'exists' not suffice for your needs ?

curl -k -X POST -Fkey=baz -Fdata='{"op": "exists", "path": ["service","ntp","server","time1.vyos.net"]}' https://192.168.122.238/retrieve|jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   349  100    46  100   303    514   3387 --:--:-- --:--:-- --:--:--  3921
{
  "success": true,
  "data": true,
  "error": null
}
curl -k -X POST -Fkey=baz -Fdata='{"op": "exists", "path": ["service","ntp","server","nonexistent"]}' https://192.168.122.238/retrieve|jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   347  100    47  100   300    506   3234 --:--:-- --:--:-- --:--:--  3771
{
  "success": true,
  "data": false,
  "error": null
}
curl -k -X POST -Fkey=baz -Fdata='{"op": "exists", "path": ["service","no","such","subpath"]}' https://192.168.122.238/retrieve|jq 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   340  100    47  100   293    547   3414 --:--:-- --:--:-- --:--:--  4000
{
  "success": true,
  "data": false,
  "error": null
}

@jestabro this is perfect, I am so sorry for creating a false feature request. The doc does not mention it, I should have looked into the server code to check first. My bad, all good now.

Well that is a fault of the docs; I will add now. Thanks !