Help us shape the future of Go! Take the 2026 Go Developer Survey

cmdutil

package
v1.3.104-alpha1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2026 License: AGPL-3.0 Imports: 37 Imported by: 0

Documentation

Overview

Package cmdutil pkg/cmdutil/catch.go c0-com-util

Package cmdutil pkg/cmdutil/climisc.go c0-com-util

Package cmdutil pkg/cmdutil/cmd_name.go c0-com-util

Package cmdutil pkg/cmdutil/dmsg_bootstrap.go c0-com-util

Package cmdutil pkg/cmdutil/inprocess.go c0-com-util

Package cmdutil pkg/cmdutil/keyfile.go c0-com-util

Package cmdutil pkg/cmdutil/legacy_flag_alias.go c0-com-util shared by every svc command that has been through a flag-rename. Maps historical flag spellings to their current canonical kebab-case form so any compose.yaml / systemd unit / shell wrapper that still passes the old name keeps working invisibly.

The renamed flag is registered ONCE under its current name; this normalizer rewrites the legacy form at parse time, so the legacy form doesn't appear in --help (no surface area pollution) but still resolves to the same target.

Package cmdutil pkg/cmdutil/service_flags.go c0-com-util

Package cmdutil pkg/cmdutil/signal_context.go c0-com-util

Package cmdutil pkg/cmdutil/signal_platform_native.go c0-com-util

Package cmdutil pkg/cmdutil/signal_unix.go c0-com-util

Package cmdutil pkg/cmdutil/skyenv.go c0-com-util

Shared SKYENV config file evaluation helpers. Used by `skywire cli config gen` and the dmsg commands.

Pre-refactor this file shelled out per-call to bash (Linux) or powershell (Windows) to expand `${VAR:-default}` and `${VAR[@]}` bash-isms against the sourced env file. The fork-per-call overhead was meaningful (a single `cli config gen` triggers ~50 of these), the bash dependency made it fragile under non-default shells, and the parallel powershell path silently differed on edge cases.

Now backed by a native Go parser in skyenv_parse.go — see that file for the exact subset of bash syntax supported.

Package cmdutil pkg/cmdutil/skyenv_parse.go c0-com-util

Native-Go parser for the SKYENV config file (/etc/skywire.conf on Linux, %ProgramData%\Skywire\skywire.conf on Windows). Replaces the previous bash-subprocess approach that called `script.Exec("bash -c 'source ${SKYENV}; printf %s')`. The bash path worked but (1) added a subshell per Skyenv* call (many called during a single `config gen`), (2) required bash on every host (Windows-side had a powershell fallback with subtly different expansion semantics), and (3) leaked the env file's secrets through ps(1) / /proc.

Scope: enough of bash variable expansion to handle what skywire's own conf template emits. Specifically:

  • KEY=value plain assignment
  • KEY='value' / KEY="value" single- or double-quoted
  • KEY=('a' 'b' 'c') bash array literal (each element optionally quoted, whitespace-separated)
  • # comment line comment (also trailing on values where the comment isn't quoted in)
  • ${VAR} simple substitution
  • ${VAR:-default} default-if-unset-or-empty
  • ${VAR-default} default-if-unset
  • ${VAR[@]} array elements (whitespace-joined for compatibility with the callers that feed the result to fmt.Sprintf %s)
  • ${VAR[@]-default} array-or-default

Intentionally NOT supported (nothing in our templates uses these): command substitution `$(…)`, nested expansions, multi-line continuations, `${VAR:offset:length}`, `${VAR/pat/repl}`. Adding any of those means we're papering over a template that's drifting into bash territory — prefer fixing the template.

Package cmdutil pkg/cmdutil/stdio.go c0-com-util

Package cmdutil pkg/cmdutil/svcconfig.go c0-com-util

Package cmdutil pkg/cmdutil/sysloghook_unix.go c0-com-util

Package cmdutil pkg/cmdutil/terminal.go c0-com-util

Package cmdutil pkg/cmdutil/terminal_native.go c0-com-util

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrTagCannotBeEmpty           = errors.New("tag cannot be empty")
	ErrTagHasInvalidChars         = errors.New("tag can only contain alphanumeric values and underscore")
	ErrTagHasMisplacedUnderscores = errors.New("tag cannot start or end with an underscore or have two underscores back-to-back")
	ErrInvalidLogString           = errors.New("failed to convert string to log level")
	ErrInvalidSyslogNet           = errors.New("network type is unsupported for syslog")
)

Associated errors.

Functions

func Catch

func Catch(v ...interface{})

Catch panics on any non-nil error.

func CatchWithLog

func CatchWithLog(log logrus.FieldLogger, msg string, v ...interface{})

CatchWithLog calls Fatal() on any non-nil error.

func CatchWithMsg

func CatchWithMsg(msg string, v ...interface{})

CatchWithMsg panics on any non-nil error with the provided message (if any).

func CommaSplit

func CommaSplit(s string) []string

CommaSplit splits a comma-separated string into trimmed, non-empty fields. It returns nil for an empty input. This centralizes the helper that several command packages previously copied.

func Eprint added in v1.3.101

func Eprint(a ...any) (int, error)

Eprint is fmt.Fprint to Stderr.

func Eprintf added in v1.3.101

func Eprintf(format string, a ...any) (int, error)

Eprintf is fmt.Fprintf to Stderr.

func Eprintln added in v1.3.101

func Eprintln(a ...any) (int, error)

Eprintln is fmt.Fprintln to Stderr.

func ExampleJSON

func ExampleJSON(v interface{}) string

ExampleJSON renders v as indented JSON for use in CLI --help example blocks. It returns "" on a marshal error. This centralizes the helper that every deployment-service command package previously copied.

func Exit added in v1.3.101

func Exit(code int)

Exit ends the command with code: the process, or only the in-process run (Run) the calling goroutine belongs to.

func Fatal added in v1.3.101

func Fatal(v ...any)

Fatal is log.Fatal through Exit.

func Fatalf added in v1.3.101

func Fatalf(format string, v ...any)

Fatalf is log.Fatalf through Exit.

func Fatalln added in v1.3.101

func Fatalln(v ...any)

Fatalln is log.Fatalln through Exit.

func LegacySvcFlagNormalizer

func LegacySvcFlagNormalizer(_ *pflag.FlagSet, name string) pflag.NormalizedName

LegacySvcFlagNormalizer is the NormalizeFunc every svc command's FlagSet should install via Flags().SetNormalizeFunc. Maps legacy flag names from the table above to their current canonical form; falls through unchanged for everything else.

func LevelFromString

func LevelFromString(s string) (logrus.Level, int, error)

LevelFromString returns a logrus.Level and syslog.Priority from a string identifier. An unrecognized (or empty) identifier yields info level plus an error naming it — never debug, which would silently make an unattended service verbose in production.

func LoadOrGenerateKey

func LoadOrGenerateKey(path string, sk *cipher.SecKey) error

LoadOrGenerateKey loads a secret key from a file, or generates a new keypair and writes it to the file if it doesn't exist. This allows systemd services to auto-generate their identity on first run without bash workarounds.

func PKFromDmsgURL

func PKFromDmsgURL(s string) cipher.PubKey

PKFromDmsgURL extracts the dmsg PK from a URL of the form `dmsg://<PK>:<port>[/path]`. Returns the zero PK when the URL is empty, malformed, or doesn't carry a valid PK in the host part. Used by callers that need the discovery's PK for dmsgfirst-style dials without forcing the operator to repeat the PK as a separate field in config.

func Print added in v1.3.101

func Print(a ...any) (int, error)

Print is fmt.Print to Stdout.

func Printf added in v1.3.101

func Printf(format string, a ...any) (int, error)

Printf is fmt.Printf to Stdout.

func Println added in v1.3.101

func Println(a ...any) (int, error)

Println is fmt.Println to Stdout.

func RootCmdName

func RootCmdName() string

RootCmdName returns the root command name.

func Run added in v1.3.101

func Run(ctx context.Context, root *cobra.Command, args []string, stdin io.Reader, stdout, stderr io.Writer) int

Run executes root with args in this process, on the given stdio, and returns the exit status a separate process of the binary would have had.

Runs may overlap, as a visor and a cli command do in one shell: each sets its stdio on the command it runs, not the root, and resets only that path's flags.

func RunRoot

func RunRoot(cmd *cobra.Command)

RunRoot executes a cobra root command and exits fatally on error. It centralizes the identical `func Execute()` wrapper that every command package (svc, apps, cli) previously copied verbatim.

func SignalContext

SignalContext returns a context that cancels on given syscall signals.

func SkyenvArray

func SkyenvArray(s, envfile string) string

SkyenvArray evaluates an array expression and returns its elements joined by commas. Used by callers that feed the result to flags expecting a comma-separated list (StringVar shaped).

func SkyenvBool

func SkyenvBool(s, envfile string) bool

SkyenvBool evaluates expr and parses it as a Go bool. Unset / empty → fall back to `:-default`; unparseable → false.

func SkyenvBoolSlice

func SkyenvBoolSlice(s, envfile string) []bool

SkyenvBoolSlice evaluates an array expression of "true"/"false" tokens and returns a bool slice. Any non-"true" element parses as false. An empty / unset variable returns [false] so callers that index `result[0]` don't panic.

func SkyenvDefault

func SkyenvDefault(s string) string

SkyenvDefault extracts the default value from a `${VAR:-default}` expression body. Public because some callers want to know "what would the fallback be" without actually sourcing the env file (e.g. constructing help text). The :- / - forms are handled the same way the parser handles them.

func SkyenvInt

func SkyenvInt(s, envfile string) int

SkyenvInt evaluates expr as a base-10 int.

func SkyenvSlice

func SkyenvSlice(expr, envfile string) ([]string, error)

SkyenvSlice sources `envfile` and expands an array expression into a string slice, one element per array entry.

func SkyenvString

func SkyenvString(s, envfile string) string

SkyenvString evaluates expr and returns the string value, falling back to the expression's `:-default` (if any) on empty / unset.

func SkyenvStringSlice

func SkyenvStringSlice(s, envfile string) []string

SkyenvStringSlice evaluates an array expression and returns the raw elements.

func SkyenvUint

func SkyenvUint(s, envfile string) uint

SkyenvUint evaluates expr as a base-10 unsigned int.

func SkyenvUintSlice

func SkyenvUintSlice(s, envfile string) []uint

SkyenvUintSlice evaluates an array expression of base-10 unsigned integers and returns a uint slice. Unparseable elements are silently dropped.

func SkyenvValue

func SkyenvValue(expr, envfile string) (string, error)

SkyenvValue sources `envfile` and evaluates the bash expression `expr`, returning the raw string result. Errors are not used — the function is best-effort: a missing file, an unrecognized expression, etc. all return "".

func Stderr added in v1.3.101

func Stderr() io.Writer

Stderr is the calling command's standard error, as Stdout.

func Stdin added in v1.3.101

func Stdin() io.Reader

Stdin is the calling command's standard input, as Stdout.

func Stdout added in v1.3.101

func Stdout() io.Writer

Stdout is where the calling command writes its output: the stdout of the in-process run (Run) it belongs to, or the process's own.

func Terminal

func Terminal() (color bool, cols int)

Terminal reports whether the calling command's standard output is a terminal that takes color, and its width in columns, 0 when not known. A command run in-process is asked about its own output, a shell's tab or pipe, not the process's, which may be a log or another terminal entirely.

func ValidTag

func ValidTag(tag string) error

ValidTag returns an error if the tag is invalid.

Types

type DmsgBootstrap

type DmsgBootstrap struct {
	Client  *dmsg.Client
	DClient disc.APIClient
	Close   func()
}

DmsgBootstrap holds the result of bootstrapping a service's DMSG connection.

func BootstrapDmsg

func BootstrapDmsg(
	ctx context.Context,
	log *logging.Logger,
	pk cipher.PubKey,
	sk cipher.SecKey,
	embeddedServers []disc.Entry,
	dmsgDisc string,
	dmsgDiscoveryDmsg string,
	dmsgServerType string,
	options ...DmsgBootstrapOption,
) (*DmsgBootstrap, error)

BootstrapDmsg creates a DMSG client for a service using the bootstrap priority:

  1. Embedded deployment config (dmsg.Prod/Test servers) — no network needed
  2. HTTP discovery fallback (only when dmsgDiscoveryDmsg is empty AND dmsgDisc is set) if embedded servers are empty

dmsgDiscoveryDmsg, when non-empty, switches the discovery fallback and the background refresh onto dmsg-HTTP — the http.Client used by the disc.APIClient gets its Transport wired to dmsghttp.MakeHTTPTransport, routing all discovery RPC over the dmsg client's sessions. No plain- HTTP egress occurs in this mode; dmsgDisc is ignored.

After connecting, a background goroutine refreshes the server list from discovery: dmsg-HTTP only when dmsgDiscoveryDmsg is set, otherwise dmsg-first with HTTP fallback.

type DmsgBootstrapOption

type DmsgBootstrapOption func(*dmsgBootstrapOpts)

DmsgBootstrapOption customizes BootstrapDmsg. Options are additive and default to the previous behavior (default carrier preference, all advertised endpoints kept), so existing callers are unaffected.

func WithCarriers

func WithCarriers(carriers ...string) DmsgBootstrapOption

WithCarriers sets the ordered dmsg CARRIER preference on the bootstrap client — how each server session's byte pipe is dialed (dmsg.CarrierWT / CarrierWS / CarrierQUIC / CarrierTCP). The first listed carrier a server advertises wins. Empty (the default) leaves dmsg's built-in preference (QUIC when advertised, else TCP).

func WithStrictCarrier

func WithStrictCarrier() DmsgBootstrapOption

WithStrictCarrier strips the TCP/QUIC fallback endpoints (Address / AddressV6 / AddressUDP / AddressUDPV6) from the bootstrap server entries, so a dial over the requested carrier cannot silently fall back to another transport. Paired with WithCarriers it makes "the session came up over carrier X" authoritative — e.g. an e2e proving dmsg-over-WebTransport actually rode WebTransport rather than quietly falling back to TCP. The browser-reachable AddressWT/AddressWS endpoints are left intact.

type DmsgConfig

type DmsgConfig struct {
	// Discovery is the HTTP URL of the dmsg-discovery the service
	// uses for its own dmsg-client lifecycle (refreshing the server
	// list, registering a client entry, etc.). Empty for services
	// that don't talk to a discovery (dmsg-discovery itself).
	Discovery string `json:"discovery,omitempty"`
	// DiscoveryDmsg is the dmsg-HTTP URL of the same discovery,
	// form `dmsg://<PK>:<port>`. Used by dmsgfirst-style clients
	// to dial the discovery over dmsg before falling back to HTTP.
	DiscoveryDmsg string `json:"discovery_dmsg,omitempty"`
	// SessionsCount is the minimum number of dmsg-server sessions
	// the service should maintain. Zero leaves it to the runtime
	// default (typically 0 — connect to all available servers).
	SessionsCount int `json:"sessions_count,omitempty"`
	// ServerType filters dmsg-servers by their declared type. Empty
	// matches all. Mirrors the existing --dmsg-server-type flag.
	ServerType string `json:"server_type,omitempty"`
	// Servers is the static dmsg-server transit set the service
	// preloads at startup. Replaces direct reads of
	// dmsg.Prod.DmsgServers at runtime — operators ship a config
	// file generated from the embedded keyring once and edit it as
	// servers rotate, no rebuild required.
	Servers []*disc.Entry `json:"servers,omitempty"`
}

DmsgConfig is the shared dmsg-related block embedded in each deployment service's config file. Mirrors the visor's `dmsg.discovery` / `dmsg.discovery_dmsg` / `dmsg.servers` shape so operators see a consistent schema across visor + every deployment service. The discovery's PK is encoded inside DiscoveryDmsg (`dmsg://<PK>:<port>`); there is no separate PK field — see PKFromDmsgURL.

Polymorphism (object vs array) is intentionally NOT supported here — deployment services don't have a multi-deployment use case the way the visor does. If that ever changes, the visor's pkg/dmsg/dmsgc.DmsgConfig is the precedent.

func (*DmsgConfig) Merge added in v1.3.98

func (d *DmsgConfig) Merge(src DmsgConfig)

Merge overlays every field src sets onto d, the way each service lays its config file over its command-line flags.

type ServiceFlags

type ServiceFlags struct {
	MetricsAddr string
	Syslog      string
	SyslogNet   string
	LogLevel    string
	Tag         string
	Config      string
	Stdin       bool
	// contains filtered or unexported fields
}

ServiceFlags represents common flags which are shared across services.

func (*ServiceFlags) Check

func (sf *ServiceFlags) Check() error

Check checks service flags.

func (*ServiceFlags) Init

func (sf *ServiceFlags) Init(rootCmd *cobra.Command, defaultTag, defaultConf string)

Init initiates the service flags. The following are performed:

  • Ensure 'defaultTag' is provided and valid.
  • Set "library" defaults.
  • Set "exec" defaults - provided by 'defaultTag' and 'defaultConf'.
  • Add flags to 'rootCmd'.

func (*ServiceFlags) Logger

func (sf *ServiceFlags) Logger() *logging.Logger

Logger returns the logger as specified by the service flags.

func (*ServiceFlags) ParseConfig

func (sf *ServiceFlags) ParseConfig(args []string, checkArgs bool, v interface{}, genDefaultFunc func() (io.ReadCloser, error)) error

ParseConfig parses config from service tags. If checkArgs is set, we additionally parse os.Args to find a config path.

type SkyenvFile

type SkyenvFile struct {
	Vars map[string][]string
}

SkyenvFile is the parsed contents of a SKYENV config file. The map values carry the source-level "shape" of the assignment: scalar assignments become a single-element slice; bash array literals stay as multi-element slices so ${VAR[@]} expansion preserves element boundaries.

func ParseSkyenvFile

func ParseSkyenvFile(path string) (*SkyenvFile, error)

ParseSkyenvFile reads `path` and returns a SkyenvFile. A missing path is NOT an error — callers (the cli config gen flag defaults) invoke this on every flag binding, well before any operator has edited /etc/skywire.conf. Empty result + nil err mirrors the old bash path's behavior on a missing file.

One level of SKYENV= redirect is honored: if the parsed file reassigns SKYENV to a different existing path, that file's contents are parsed second and overlay the first. Mirrors the "source twice" pattern the previous bash implementation used so operators with `/etc/skywire.conf → ~/.config/skywire.conf` redirects keep the same behavior.

func (*SkyenvFile) Eval

func (f *SkyenvFile) Eval(expr string) string

Eval evaluates a single ${...} expression against f. Returns the expanded string. Mirrors the subset of bash expansion the old `script.Exec("bash -c 'printf %s' ${expr}")` path produced.

Recognized expressions:

${VAR}                  → value of VAR (empty if unset)
${VAR:-default}         → value of VAR if set+non-empty, else default
${VAR-default}          → value of VAR if set, else default
${VAR[@]}               → array elements joined with space
${VAR[@]-default}       → array elements if set, else default

Anything that doesn't start with `${` and end with `}` is returned verbatim — same forgiving behavior as the bash path.

func (*SkyenvFile) EvalSlice

func (f *SkyenvFile) EvalSlice(expr string) []string

EvalSlice returns the array form. Unlike Eval which joins, this preserves element boundaries — used by SkyenvSlice / SkyenvStringSlice callers that need to range over the result.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL