Trying to upload alert rules in .yaml format using a curl command?

I asked a question last week and now that I’ve had some time to try it out I need to ask another. I’m not sure if this is specifically a PMM question, it might be better on StackOverflow, but since it’s a piece of PMM, I’m hoping someone has already run into this.
So, I have an alert_rules.yaml file, with some simple Prometheus alert rules that I want to upload to PMM via the API. I then have a bash script that runs on startup of the PMM docker container that should run the command to run the query with the alert_rules.yaml file as an input (here called by the variable ${alertfile}:

curl -X POST "http://localhost/v1/Settings/Change" -H "accept: application/json" 
-H "Content-Type: application/json" -u "u":"p" 
-d "{ \"alert_manager_url\": \"${alertmanager_url}\", \"alert_manager_rules\": \"${alertfile}\"}"<br>

I end up with the error:

{“error”:“invalid character ‘\n’ in string literal”,“code”:3,“message”:“invalid character ‘\n’ in string literal”}

Clearly, I’m having a problem with escaping special characters correctly, I’ve tried every combination of , ’ and " that I can think of. But then here is the other problem: How am I supposed to get an entire block of yaml through a JSON API with spaces and returns intact? Is there an easier way to go about this? I figured if it was designed this way, someone must have done it already, and might have the solution?

Hi Jeff,

Here is an example of a working command

curl -s -X POST "http://admin:password@1.2.3.4/v1/Settings/Change" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"enable_telemetry\": true, \"metrics_resolutions\": { \"hr\": \"5s\", \"mr\": \"15s\", \"lr\": \"60s\" }, \"data_retention\": \"2592000s\", \"alert_manager_url\": \"http://localhost:9090\", \"alert_manager_rules\": \"groups:\n- name: PostgresqlStatus\n &nbsp;rules:\n &nbsp;- alert: PostgresqlDown\n &nbsp;&nbsp;&nbsp;expr: pg_up == 0\n &nbsp;&nbsp;&nbsp;for: 5m\n &nbsp;&nbsp;&nbsp;labels:\n &nbsp;&nbsp;&nbsp;annotations:\n &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;summary: \n &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description: \"}"

I’m going to edit my previous response because while the above answer makes sense, it doesn’t seem very usable. The AlertRules section of that call could potentially be very long, and if I’m going to be adding in a new rule for instance, I’m going to be doing it in .yaml format. Do I then have to go back every time I add, change or remove a rule, and manually type in escaped lines to get my .yaml document in a single line? I’m just thinking, I could do this once, as long as I knew my YAML was all configured correctly, but anytime i want to add or update the rule (and subsequently have that added as part of a deployment process and not just going into the UI to edit it) that’s going to be very difficult. 

I was going to say that I think your file is being interpreted incorrectly on ingestion…you could use something like sed to replace the \n with a \n which would make the file unreadable but likely would be accepted as input.  Might just create a side script to sed/awk it at run-time so you can be making edits to the easy to read file and then at the last minute convert to a temp file as one long line of escaped text to be passed as part of the command. 

That dislodged something in my brain, sed was the answer. In case anyone finds this in the future I found this thread on Stack Overflow and repurposed it for this need: https://stackoverflow.com/questions/1251999/how-can-i-replace-a-newline-n-using-sed

sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/\\n/g' alertfile.yml<br>

The above changes newlines in the alertfile.yml document to the characters “\n” and makes the whole document to a single line, which I can then input into the curl command.