lxc/incus

alias evaluation is not deterministic

Closed this issue · 4 comments

Required information

  • Distribution: Ubuntu
  • Distribution version: 22
  • Kernel version: 6.8.0-40-generic
  • LXC version: 6.0.0
  • Incus version: zabbly 1:6.5-ubuntu22.04-202409162056

Issue description

alias evaluation is not deterministic. reissuing same aliased command has random effect.

Steps to reproduce

 $ incus alias list -f compact | grep prof
  prof        profile                  
  prof ls     profile list -f compact  
  profile ls  profile list -f compact  

 $ incus prof ls
+---------+-----------------------+---------+
|  NAME   |      DESCRIPTION      | USED BY |
+---------+-----------------------+---------+
| default | Default Incus profile | 0       |
+---------+-----------------------+---------+

 $ incus prof ls
   NAME         DESCRIPTION       USED BY  
  default  Default Incus profile  0        

 $ incus prof ls
   NAME         DESCRIPTION       USED BY  
  default  Default Incus profile  0        

 $ incus prof ls
+---------+-----------------------+---------+
|  NAME   |      DESCRIPTION      | USED BY |
+---------+-----------------------+---------+
| default | Default Incus profile | 0       |
+---------+-----------------------+---------+

note how sometimes compact is in effect, other times it is not, although it's the same command. It seems roughly even, with a little bias towards ignoring format:

 $ unset hits; declare -A hits; \
   for ((i = 0; i < 1000; i++))
   do len=$(incus prof ls | wc -l); let "hits[$len]++"; done; \
   for hit in ${!hits[@]}; do echo "$hit:${hits[$hit]}"; done
5:589
2:411

In Go, dictionaries are not sorted so the order when accessed is basically random, leading to what we see here.

We can probably get the dict keys, sort them alphabetically and then process the map to have a consistent order.

Why does one of the possibilities it's cycling between, not have the -f compact? For these alias definitions:

prof        profile                  
prof ls     profile list -f compact  
profile ls  profile list -f compact  

both forms with the ls have -f compact. So why is incus prof ls resolving to any possibility without it? Stranger still, it knows enough to expand the list part but drops the -f compact !?

Note, they were defined like:

 $ incus alias add "prof ls" "profile list -f compact"

I suspect it's because we don't re-enter alias evaluation.

So when the matching alias is your prof=profile one, then you don't get the argument.

maybe it should match command line against possible alias matches in longest to shortest alias order.

recursive alias evaluation could be useful. loop detected could end recursion.

partial/stem/prefix command word matching would help too. a lot of aliases wouldn't be necessary then.