The UX of az vm run-command invoke is abysmal
See original GitHub issueDescribe the bug
The UX of az vm run-command invoke
is abysmal:
- The output is encoded in a pointless, bad DSL
640 KiB4 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.)
Issue Analytics
- State:
- Created a year ago
- Comments:5 (1 by maintainers)
Top GitHub Comments
It would be great to have the output sans DSL. Right now you need to use things like sed after jq to format it from json:
jq .value[].message | sed -e 's/\[stderr\]\\n"//g' -e 's/"Enable succeeded: \\n\[stdout]\\n//g'
… etcThe bespoke output format and 4K limit definitely make this difficult to use.