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:
- Add a new endpoint for the API, my suggestion: /has
- Add a new operation to the /retrieve endpoint, my suggestion: hasConfig
- 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.