Files
zeekayandHanzo Dev 0fd5c6b353 an off-switch that does nothing is worse than one that is not there
Six env flags, two conventions, and both failed silently against the other.
Five read `== "true"`, so BOOTNODE_ENABLED=1 left bootnode off and
CALENDAR_ENABLED=1 left the calendar off. One read `!= "1"`, so
BASE_ENABLE_ADMIN_UI=true served no admin. And ZAP_DISABLED read `!= "true"`, so
an operator who wrote ZAP_DISABLED=1 to stop the listener watched it come up
anyway. In every case the flag was accepted, ignored, and never mentioned again.

This tree already answers "read a boolean from a string" four times, with
strconv.ParseBool (tools/filesystem, tools/search, tools/router,
core/settings_query). The hand-rolled comparisons were the deviation, so
osutils.Bool is that answer given a name and a default, and all six sites read
it. Strictly more permissive: every spelling that worked before still works, and
the ones that silently did nothing now do what they say.

An unparseable value yields the default rather than its opposite — someone who
typed something meaningless has not asked for the other thing.

Coverage: plugins/zap 5.9% -> 23.5%, and DefaultConfig is pinned including the
case that started this (ZAP_DISABLED=1 must disable) and a garbage ZAP_PORT,
which must keep 9999 rather than quietly binding somewhere else.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-24 10:34:54 -07:00

33 lines
1.1 KiB
Go

package osutils
import (
"os"
"strconv"
"strings"
)
// Bool reads name from the environment as a boolean, returning def when it is
// unset, empty, or not something a boolean can be read from.
//
// It accepts what strconv.ParseBool accepts — 1/t/T/TRUE/true/True and their
// false counterparts — which is the answer the rest of this tree already gives
// (tools/filesystem, tools/search, core/settings_query all parse booleans that
// way). The hand-rolled `== "true"` and `!= "1"` checks were the deviation, and
// each turned a reasonable spelling into silence: BOOTNODE_ENABLED=1 left
// bootnode off, ZAP_DISABLED=1 left the listener up, and neither said so. An
// operator's off-switch that does nothing is worse than one that does not exist.
//
// An unparseable value yields def rather than its opposite: someone who wrote
// something meaningless has not asked for the other thing.
func Bool(name string, def bool) bool {
raw := strings.TrimSpace(os.Getenv(name))
if raw == "" {
return def
}
v, err := strconv.ParseBool(raw)
if err != nil {
return def
}
return v
}