Cannot write command tests without shell (sh)
Describe the bug
Goss command test will execute the command wrapped with a sh -c "<the command>".
This assumes sh executable exists.
When testing distroless containers with a single binary, goss cannot execute the binary.
Dockerfile
FROM scratch
ADD figlet /
ENTRYPOINT ["figlet"]
goss.yaml
Command: figlet: exit-status:
Error
exec: "sh": executable file not found in $PATH
How To Reproduce
Create a single statically compiled binary, or a binary with the needed libraries.
For me it is figlet.
command:
figlet:
exec: figlet test
Expected Behavior
Goss to directly execute (without a shell in the middle) figlet (arg 0) with single argument test (arg 1).
I think that goss giving a shell, should be configurable - and optional.
Perhaps a new attribute shell that defaults to sh, and if explicitly set to nothing shell:, then goss will exec directly the command, rather than running it in a shell.
Actual Behavior
Goss attempts to execute sh, which doesn't exist, so fails.
Environment:
- Version of goss: goss version v0.4.4
- OS/Distribution version (if applicable): Alpine Linux
Not sure this is a bug to be honest.
The documentation should be clarified that Goss uses sh -c under the hood so things like pipes and redirects work properly. (E.g. grep xx < somefile | sort)
Perhaps there's a feature request in here to allow exec to workout without shell no-shell: true or something like that for situations like this.
I'm going to raise a PR because this is blocking what I am trying to use goss for. Would you be open to that, and if so, which would you prefer:
1. Specify Shell
Allows specifying an alternative shell or specifying no shell.
Use Case 1: Straight Exec
command:
figlet:
exec: figlet test
# no shell (straight exec)
shell: ""
Use Case 2: Zsh
command:
zshism:
# Use zsh glob qualifier to show files modified in the last day
exec: "echo *(.m-1)"
shell: zsh
2. Can opt out of shell
In this case the command is either (by default) executed with sh -c , or can optionally be directly executed.
Use Case 1:
Use Case 1: Straight Exec
command:
figlet:
exec: figlet test
# no shell (straight exec)
# naming of this could be `no-shell`?
shell: false
Use Case 2: Zsh
You can't override which shell is used, but you can just directly execute the shell.
command:
zshism:
shell: false
# Use zsh glob qualifier to show files modified in the last day
exec: |-
zsh -c "echo *(.m-1)"
3. Only exec, if user wants a shell, they need to specify it
Use Case 1:
Use Case 1: Straight Exec
command:
figlet:
exec: figlet test
Use Case 2: Zsh
User wants to use a shell, so they specify it as part of the command to be executed.
command:
zshism:
# Use zsh glob qualifier to show files modified in the last day
exec: |-
zsh -c "echo *(.m-1)"
More thoughts
I like the simplicity of the third solution, but it is a breaking change.
The second solution is relatively simple and backwards compatible. Simple true/false for shell. If a user wants to use bash, or zsh etc, they can just write the full command like in the example I gave. This is simpler solution than first one because maybe some shells won't use -c for the command, and users might complain that some esoteric shell doesn't work as expected.
What do you think?
I agree this is more a feature request. If it's possible to change the label?
I prefer option 2 for all the reasons you outlined above.
Also, since Goss has been around for ~8 years without this issue, opting out seems sensible, likely needed only by a few users.