Describe the bug
The UX of az vm run-command invoke is abysmal:
- The output is encoded in a pointless, bad DSL
640 KiB 4 KiB should be enough for anyone.
- It is slower than 🐌
Despite emitting JSON, the bits anyone cares about (the output of the command) is encoded is an ambiguous DSL
Take an example run:
» az vm run-command invoke -g example-rg -n example-rg --command-id RunShellScript --scripts 'ls -la'
{
"value": [
{
"code": "ProvisioningState/succeeded",
"displayStatus": "Provisioning succeeded",
"level": "Info",
"message": "Enable succeeded: \n[stdout]\ntotal 12\ndrwx------ 2 root root 4096 May 2 20:37 .\ndrwx------ 36 root root 4096 May 2 20:37 ..\n-r-x------ 1 root root 7 May 2 20:37 script.sh\n-rw------- 1 root root 0 May 2 20:37 stderr\n-rw------- 1 root root 0 May 2 20:37 stdout\n\n[stderr]\n",
"time": null
}
]
}
The bit we care about is the output; we can ask either az to make that more legible, or we can run it through | jq -r. Either way nets one:
Enable succeeded:
[stdout]
total 12
drwx------ 2 root root 4096 May 2 20:37 .
drwx------ 36 root root 4096 May 2 20:37 ..
-r-x------ 1 root root 7 May 2 20:37 script.sh
-rw------- 1 root root 0 May 2 20:37 stderr
-rw------- 1 root root 0 May 2 20:37 stdout
[stderr]
… so here, we have three pieces of actual data: the stdout, the stderr, and … whatever the heck "Enable succeeded" is or signifies. This just came out of JSON, a way to represent structured data, it could have been,
{
"enableSucceeded": true,
"stdout": "<the data for stdout…>",
"stderr": "<similar…>"
}
… and parsing would have been mind-bogglingly simple. One could have used the built in facilities of az's --query, even.
But instead, what we've got (the above text blob) is some stringly typed data; if we want to get, e.g., the output, we've got to parse that ourselves. And if you try this, you should also realize that the output's language is ambiguous: our parser cannot know whether [stderr] signifies the end of stdout, or if that string literally appeared in the output. To avoid this, you have to implement some sort of escaping mechanism in the script you pass to be run on the remote, to guarantee that output won't appear.
Now I realize there is some level of "plugins" occurring here (i.e., the arg to --command-id) but that's not a salient reason for the troubles here. At the worst, the message string could have been JSON, or whatever interface these communicate via could have just been made more powerful than a simple text message…
640 KiB 4 KiB should be enough for anyone: you're limited to only returning 4 paltry KiB of data. Examples of command that one might run that would exceed this? ps -ef, for example. ls. Simple stuff, but you're forced to sip through a coffee stir.
You can work around this, of course, by piping the output to a file on the remote. The response is also a JSON string, which can't handle binary, so to ensure everything gets over the write alright, | gzip | base64 — this has the added benefits of avoiding the ambiguity problems in point 1, as base64 will never emit [stderr].
Then write a script that does that for you, then transfers that output file in chucks through multiple invocations of az vm run-command invoke.
It is slower than 🐌: It takes ~30s per command. At a rate of 4KiB per command, that works out to a total bit rate of ~1,000 bps. That's bits per second. In the year 2022.
Add all this together, and running ps -ef over this channel takes, all told, 2m 8s.
To Reproduce
Run the command more than once.
Expected behavior
My sanity remains intact, and I don't have to do so much work to get stuff done.
Environment summary
brew install. macOS. Let's be honest it's going to be equally bad no matter the environment.
Additional context
While debugging this, I discovered a but in my terminal, too. So there's that.
Holistically, these problems are more pervasive than just az. The Azure "REST" APIs also having pagination limits that result in tiny transfers per request, and are slow. (E.g., some of ACR's APIs have bandwidths best measured in "baud" as well.)
Describe the bug
The UX of
az vm run-command invokeis abysmal:640 KiB4 KiB should be enough for anyone.Despite emitting JSON, the bits anyone cares about (the output of the command) is encoded is an ambiguous DSL
Take an example run:
The bit we care about is the output; we can ask either
azto make that more legible, or we can run it through| jq -r. Either way nets one:… so here, we have three pieces of actual data: the
stdout, thestderr, and … whatever the heck "Enable succeeded" is or signifies. This just came out of JSON, a way to represent structured data, it could have been,{ "enableSucceeded": true, "stdout": "<the data for stdout…>", "stderr": "<similar…>" }… and parsing would have been mind-bogglingly simple. One could have used the built in facilities of
az's--query, even.But instead, what we've got (the above text blob) is some stringly typed data; if we want to get, e.g., the output, we've got to parse that ourselves. And if you try this, you should also realize that the output's language is ambiguous: our parser cannot know whether
[stderr]signifies the end ofstdout, or if that string literally appeared in the output. To avoid this, you have to implement some sort of escaping mechanism in the script you pass to be run on the remote, to guarantee that output won't appear.Now I realize there is some level of "plugins" occurring here (i.e., the arg to
--command-id) but that's not a salient reason for the troubles here. At the worst, themessagestring could have been JSON, or whatever interface these communicate via could have just been made more powerful than a simple text message…640 KiB4 KiB should be enough for anyone: you're limited to only returning 4 paltry KiB of data. Examples of command that one might run that would exceed this?ps -ef, for example.ls. Simple stuff, but you're forced to sip through a coffee stir.You can work around this, of course, by piping the output to a file on the remote. The response is also a JSON string, which can't handle binary, so to ensure everything gets over the write alright,
| gzip | base64— this has the added benefits of avoiding the ambiguity problems in point 1, as base64 will never emit[stderr].Then write a script that does that for you, then transfers that output file in chucks through multiple invocations of
az vm run-command invoke.It is slower than 🐌: It takes ~30s per command. At a rate of 4KiB per command, that works out to a total bit rate of ~1,000 bps. That's bits per second. In the year 2022.
Add all this together, and running
ps -efover this channel takes, all told, 2m 8s.To Reproduce
Run the command more than once.
Expected behavior
My sanity remains intact, and I don't have to do so much work to get stuff done.
Environment summary
brew install. macOS. Let's be honest it's going to be equally bad no matter the environment.Additional context
While debugging this, I discovered a but in my terminal, too. So there's that.
Holistically, these problems are more pervasive than just
az. The Azure "REST" APIs also having pagination limits that result in tiny transfers per request, and are slow. (E.g., some of ACR's APIs have bandwidths best measured in "baud" as well.)