Files
myos/spec/unit/expose_spec.sh
Yann Autissier be777fc9e6 read the exposure scope from the compose file, drop the _EXPOSE variable
The variable declared an intent and changed nothing: it fed the report and
never the binding, so it could say public while the file published on the
loopback, or the reverse. A declaration that cannot be wrong is better than one
that has to be kept in step.

The scope is now which binding the file asks for, read from the compose files
as written: ${MYOS_BIND_PUBLIC} is public, a hand-written address is pinned,
and a bare '- 80' or '9000:9000' is unbound, meaning docker opens it on every
address and nobody chose that. --strict fails on those.

Reading the resolved configuration instead would lose the distinction: every
form ends up as a plain address, and an unbound port looks exactly like a
deliberate public one.

What is left to configure per host is the address of each scope, which is the
part that belongs to the host rather than to the stack.
2026-09-05 13:22:04 +02:00

101 lines
3.6 KiB
Bash

#shellcheck shell=sh
Include lib/core.sh
Include lib/str.sh
Include lib/var.sh
Include lib/tags.sh
Include lib/naming.sh
Include lib/stack.sh
Include lib/expose.sh
# Docker writes its own firewall rules, so a port published to 0.0.0.0 answers
# the internet whatever the host firewall says. Binding the publication is the
# portable answer: it behaves the same on linux and on macOS, without root.
Describe 'lib/expose.sh'
Describe 'myos_bind'
It 'binds the private scope to the loopback'
When call myos_bind private
The output should equal "127.0.0.1"
End
It 'binds the public scope to every address'
When call myos_bind public
The output should equal "0.0.0.0"
End
It 'takes an explicit address over the default'
MYOS_BIND_PRIVATE=10.0.0.1
When call myos_bind private
The output should equal "10.0.0.1"
End
It 'keeps an unknown scope private rather than public'
When call myos_bind nonsense
The output should equal "127.0.0.1"
End
It 'falls back to the private address when there is no mesh'
MYOS_MESH_IFACE=nosuchiface0
When call myos_bind mesh
The output should equal "127.0.0.1"
End
It 'uses the mesh address when one is given'
MYOS_BIND_MESH=10.144.0.2
When call myos_bind mesh
The output should equal "10.144.0.2"
End
End
Describe 'myos_stack_prefix'
Parameters
"host/fabio" "HOST_FABIO"
"User/ipfs" "USER_IPFS"
"supabase" "SUPABASE"
"drone/drone" "DRONE"
End
It "prefixes the settings of $1 with $2"
When call myos_stack_prefix "$1"
The output should equal "$2"
End
End
Describe 'myos_expose_declared'
setup() { MYOS_TMP=$(mktemp -d "${TMPDIR:-/tmp}/myos-exp.XXXXXX"); }
cleanup() { rm -rf "$MYOS_TMP"; }
BeforeEach setup
AfterEach cleanup
# The scope is not declared on the side: it is which binding the compose
# file asks for. Reading the resolved configuration instead would lose the
# difference, since every form ends up as a plain address.
It 'reads the scope out of the binding each port asks for'
printf 'services:\n a:\n ports:\n' > "$MYOS_TMP/c.yml"
printf ' - "${MYOS_BIND_PUBLIC}:443:443"\n' >> "$MYOS_TMP/c.yml"
printf ' - "${MYOS_BIND_PRIVATE}::8080"\n' >> "$MYOS_TMP/c.yml"
printf ' - "${MYOS_BIND_MESH}::7946"\n' >> "$MYOS_TMP/c.yml"
printf ' - "127.0.0.1:5432:5432"\n' >> "$MYOS_TMP/c.yml"
printf ' - 80\n' >> "$MYOS_TMP/c.yml"
When call myos_expose_declared "$MYOS_TMP/c.yml"
The line 1 should equal "a|443|public"
The line 2 should equal "a|8080|private"
The line 3 should equal "a|7946|mesh"
The line 4 should equal "a|5432|pinned"
The line 5 should equal "a|80|unbound"
End
It 'calls a plain host:container mapping unbound, because it is'
printf 'services:\n a:\n ports:\n - "9000:9000"\n - 25:25\n' > "$MYOS_TMP/c.yml"
When call myos_expose_declared "$MYOS_TMP/c.yml"
The line 1 should equal "a|9000|unbound"
The line 2 should equal "a|25|unbound"
End
It 'keeps the protocol out of the port'
printf 'services:\n a:\n ports:\n - 4001/udp\n' > "$MYOS_TMP/c.yml"
When call myos_expose_declared "$MYOS_TMP/c.yml"
The output should equal "a|4001|unbound"
End
It 'reports nothing for a service that publishes nothing'
printf 'services:\n a:\n image: alpine\n' > "$MYOS_TMP/c.yml"
When call myos_expose_declared "$MYOS_TMP/c.yml"
The output should equal ""
End
End
End