cmd/apigw/main.go
Source
- Package:
main - File:
cmd/apigw/main.go - GitHub: https://github.com/theroutercompany/api_router/blob/main/cmd/apigw/main.go
Overview
What:
CLI entrypoint for operating the gateway.
This command is the primary user-facing interface for:
- running the gateway (
run) - validating config (
validate) - generating a sample config (
init) - managing a background daemon (
daemon) - calling the control-plane admin endpoints (
admin) - snapshotting env-based config into YAML (
convert-env)
Why:
The gateway is designed to be both embeddable and operable. A thin CLI makes it easy to run locally, integrate with deployment scripts, and manage long-running processes without forcing a specific process manager.
How:
main() dispatches based on the first CLI argument.
Each subcommand parses its own flags and then calls into shared packages:
pkg/gateway/configfor config loading/validationpkg/gateway/runtimefor runtime lifecycle (including reload callback)pkg/gateway/daemonfor PID-file based daemon management
Notes: The CLI does not attempt to hide secrets beyond what the admin endpoints do. Avoid printing full configs with secrets to logs/terminals in production.
Contents
Imports
import block 1
import (
"context"
"errors"
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
"os/signal"
"path/filepath"
"strconv"
"strings"
"syscall"
"time"
"github.com/fsnotify/fsnotify"
"gopkg.in/yaml.v3"
gatewayconfig "github.com/theroutercompany/api_router/pkg/gateway/config"
gatewaydaemon "github.com/theroutercompany/api_router/pkg/gateway/daemon"
gatewayruntime "github.com/theroutercompany/api_router/pkg/gateway/runtime"
)
Constants
const block 1
const daemonChildEnv = "APIGW_DAEMON_CHILD"
daemonChildEnv
What: Environment variable used to mark a background daemon child process.
Why: Prevents recursive respawning when apigw daemon start --background launches a child that should run in the foreground.
How: The parent sets APIGW_DAEMON_CHILD=1 on the child process environment; the child checks it to decide whether to spawn again.
const block 2
const sampleConfigYAML = `# Gateway configuration for the API router.
version: ""
http:
port: 8080
shutdownTimeout: 15s
readiness:
timeout: 2s
userAgent: api-router-gateway/readyz
upstreams:
- name: trade
baseURL: https://trade.example.com
healthPath: /health
tls:
enabled: false
insecureSkipVerify: false
caFile: ""
clientCertFile: ""
clientKeyFile: ""
- name: task
baseURL: https://task.example.com
healthPath: /health
tls:
enabled: false
insecureSkipVerify: false
caFile: ""
clientCertFile: ""
clientKeyFile: ""
auth:
secret: replace-me
issuer: router
audiences:
- api
cors:
allowedOrigins:
- https://app.example.com
rateLimit:
window: 60s
max: 120
metrics:
enabled: true
`
sampleConfigYAML
What: Embedded sample YAML used by the init command.
Why: Provides a quick starting point without requiring users to copy files from the repo.
How: Writes this string to disk in initCommand (optionally overwriting via --force).
Functions and Methods
main
What: Program entrypoint that dispatches to subcommands.
Why: Keeps the CLI simple and avoids a large framework for a small command surface.
How: Switches on os.Args[1], calls the matching command function, and exits non-zero on error.
func main() {
if len(os.Args) < 2 {
usage()
os.Exit(1)
}
var err error
switch os.Args[1] {
case "run":
err = runCommand(os.Args[2:])
case "validate":
err = validateCommand(os.Args[2:])
case "init":
err = initCommand(os.Args[2:])
case "daemon":
err = daemonCommand(os.Args[2:])
case "admin":
err = adminCommand(os.Args[2:])
case "convert-env":
err = convertEnvCommand(os.Args[2:])
default:
usage()
os.Exit(1)
}
if err != nil {
log.Fatalf("apigw %s: %v", os.Args[1], err)
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L29:
if len(os.Args) < 2 { usage() os.Exit(1) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L30:
usage()- What: Calls usage.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L31:
os.Exit(1)- What: Calls os.Exit.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L30:
- L34:
var err error- What: Declares local names.
- Why: Introduces variables or types used later in the function.
- How: Executes a Go declaration statement inside the function body.
- L35:
switch os.Args[1] { case "run": err = runCommand(os.Args[2:]) case "validate": err = validateCommand(os.Args[2:]) case "init": err = initCo…- What: Selects a branch from multiple cases.
- Why: Keeps multi-case branching readable and explicit.
- How: Evaluates the switch expression and executes the first matching case.
- Nested steps:
- L36:
case "run":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L37:
err = runCommand(os.Args[2:])- What: Assigns err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L37:
- L38:
case "validate":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L39:
err = validateCommand(os.Args[2:])- What: Assigns err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L39:
- L40:
case "init":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L41:
err = initCommand(os.Args[2:])- What: Assigns err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L41:
- L42:
case "daemon":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L43:
err = daemonCommand(os.Args[2:])- What: Assigns err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L43:
- L44:
case "admin":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L45:
err = adminCommand(os.Args[2:])- What: Assigns err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L45:
- L46:
case "convert-env":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L47:
err = convertEnvCommand(os.Args[2:])- What: Assigns err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L47:
- L48:
default:- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L49:
usage()- What: Calls usage.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L50:
os.Exit(1)- What: Calls os.Exit.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L49:
- L36:
- L53:
if err != nil { log.Fatalf("apigw %s: %v", os.Args[1], err) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L54:
log.Fatalf("apigw %s: %v", os.Args[1], err)- What: Calls log.Fatalf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L54:
runCommand
What: Implements apigw run to start the gateway runtime and optionally hot-reload on config changes.
Why: Provides the primary "run the gateway locally/in containers" workflow with an optional file watcher.
How: Loads config, builds a runtime with a reload callback, optionally starts a config watcher, and loops handling OS signals, runtime exit, watcher errors, and reload requests by stopping and restarting the runtime with rt.Reload.
func runCommand(args []string) error {
fs := flag.NewFlagSet("run", flag.ExitOnError)
configPath := fs.String("config", "", "Path to gateway configuration file")
watch := fs.Bool("watch", false, "Watch the config file for changes and hot-reload")
if err := fs.Parse(args); err != nil {
return err
}
opts := []gatewayconfig.Option{}
if *configPath != "" {
opts = append(opts, gatewayconfig.WithPath(*configPath))
}
cfg, err := gatewayconfig.Load(opts...)
if err != nil {
return fmt.Errorf("load config: %w", err)
}
reloadRequests := make(chan gatewayconfig.Config, 1)
enqueueReload := func(cfg gatewayconfig.Config) {
select {
case reloadRequests <- cfg:
default:
go func() { reloadRequests <- cfg }()
}
}
reloadFunc := func() (gatewayconfig.Config, error) {
cfg, err := gatewayconfig.Load(opts...)
if err != nil {
return gatewayconfig.Config{}, err
}
enqueueReload(cfg)
return cfg, nil
}
rt, err := gatewayruntime.New(cfg, gatewayruntime.WithReloadFunc(reloadFunc))
if err != nil {
return fmt.Errorf("build runtime: %w", err)
}
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()
var (
watchErrCh <-chan error
watchCancel context.CancelFunc
)
if *watch {
if *configPath == "" {
return errors.New("--config is required when --watch is enabled")
}
watchReloadCh, errCh, cancelWatch, err := watchConfig(ctx, *configPath, opts)
if err != nil {
return fmt.Errorf("watch config: %w", err)
}
watchErrCh = errCh
watchCancel = cancelWatch
go func() {
for cfg := range watchReloadCh {
enqueueReload(cfg)
}
}()
}
defer func() {
if watchCancel != nil {
watchCancel()
}
}()
runCtx, runCancel := context.WithCancel(ctx)
runDone := make(chan error, 1)
go func() {
runDone <- rt.Run(runCtx)
}()
for {
select {
case err := <-runDone:
runCancel()
if err != nil && !errors.Is(err, context.Canceled) {
return err
}
return nil
case cfg := <-reloadRequests:
runCancel()
if err := <-runDone; err != nil && !errors.Is(err, context.Canceled) {
return err
}
if err := rt.Reload(cfg); err != nil {
return fmt.Errorf("reload config: %w", err)
}
runCtx, runCancel = context.WithCancel(ctx)
runDone = make(chan error, 1)
go func() {
runDone <- rt.Run(runCtx)
}()
log.Printf("configuration reloaded")
case err, ok := <-watchErrCh:
if !ok {
watchErrCh = nil
continue
}
if err != nil {
log.Printf("config watch error: %v", err)
}
case <-ctx.Done():
runCancel()
}
}
}
Walkthrough
Expand walkthrough (84 steps)
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L59:
fs := flag.NewFlagSet("run", flag.ExitOnError)- What: Defines fs.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L60:
configPath := fs.String("config", "", "Path to gateway configuration file")- What: Defines configPath.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L61:
watch := fs.Bool("watch", false, "Watch the config file for changes and hot-reload")- What: Defines watch.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L62:
if err := fs.Parse(args); err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L62:
err := fs.Parse(args)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L63:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L62:
- L66:
opts := []gatewayconfig.Option{}- What: Defines opts.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L67:
if *configPath != "" { opts = append(opts, gatewayconfig.WithPath(*configPath)) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L68:
opts = append(opts, gatewayconfig.WithPath(*configPath))- What: Assigns opts.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L68:
- L71:
cfg, err := gatewayconfig.Load(opts...)- What: Defines cfg, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L72:
if err != nil { return fmt.Errorf("load config: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L73:
return fmt.Errorf("load config: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L73:
- L76:
reloadRequests := make(chan gatewayconfig.Config, 1)- What: Defines reloadRequests.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L77:
enqueueReload := func(cfg gatewayconfig.Config) { select { case reloadRequests <- cfg: default: go func() { reloadRequests <- cfg }() } }- What: Defines enqueueReload.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- Nested steps:
- L77:
func(cfg gatewayconfig.Config) { select { case reloadRequests <- cfg: default: go func() { reloadRequests <- cfg }() } }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L78:
select { case reloadRequests <- cfg: default: go func() { reloadRequests <- cfg }() }- What: Selects among concurrent operations.
- Why: Coordinates channel operations without blocking incorrectly.
- How: Executes a
selectstatement and runs one ready case. - Nested steps:
- L79:
case reloadRequests <- cfg:- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- L80:
default:- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- Nested steps:
- L81:
go func() { reloadRequests <- cfg }()- What: Starts a goroutine.
- Why: Runs work concurrently.
- How: Invokes the function call asynchronously using
go. - Nested steps:
- L81:
func() { reloadRequests <- cfg }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L81:
reloadRequests <- cfg- What: Sends a value on a channel.
- Why: Communicates with another goroutine.
- How: Executes a channel send operation.
- L81:
- L81:
- L81:
- L79:
- L78:
- L77:
- L85:
reloadFunc := func() (gatewayconfig.Config, error) { cfg, err := gatewayconfig.Load(opts...) if err != nil { return gatewayconfig.Config{},…- What: Defines reloadFunc.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- Nested steps:
- L85:
func() (gatewayconfig.Config, error) { cfg, err := gatewayconfig.Load(opts...) if err != nil { return gatewayconfig.Config{}, err } enqueue…- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L86:
cfg, err := gatewayconfig.Load(opts...)- What: Defines cfg, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L87:
if err != nil { return gatewayconfig.Config{}, err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L88:
return gatewayconfig.Config{}, err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L88:
- L90:
enqueueReload(cfg)- What: Calls enqueueReload.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L91:
return cfg, nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L86:
- L85:
- L94:
rt, err := gatewayruntime.New(cfg, gatewayruntime.WithReloadFunc(reloadFunc))- What: Defines rt, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L95:
if err != nil { return fmt.Errorf("build runtime: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L96:
return fmt.Errorf("build runtime: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L96:
- L99:
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)- What: Defines ctx, cancel.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L100:
defer cancel()- What: Defers a call for cleanup.
- Why: Ensures the deferred action runs even on early returns.
- How: Schedules the call to run when the surrounding function returns.
- L102:
var ( watchErrCh <-chan error watchCancel context.CancelFunc )- What: Declares local names.
- Why: Introduces variables or types used later in the function.
- How: Executes a Go declaration statement inside the function body.
- L106:
if *watch { if *configPath == "" { return errors.New("--config is required when --watch is enabled") } watchReloadCh, errCh, cancelWatch, e…- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L107:
if *configPath == "" { return errors.New("--config is required when --watch is enabled") }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L108:
return errors.New("--config is required when --watch is enabled")- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L108:
- L110:
watchReloadCh, errCh, cancelWatch, err := watchConfig(ctx, *configPath, opts)- What: Defines watchReloadCh, errCh, cancelWatch, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L111:
if err != nil { return fmt.Errorf("watch config: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L112:
return fmt.Errorf("watch config: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L112:
- L114:
watchErrCh = errCh- What: Assigns watchErrCh.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L115:
watchCancel = cancelWatch- What: Assigns watchCancel.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L116:
go func() { for cfg := range watchReloadCh { enqueueReload(cfg) } }()- What: Starts a goroutine.
- Why: Runs work concurrently.
- How: Invokes the function call asynchronously using
go. - Nested steps:
- L116:
func() { for cfg := range watchReloadCh { enqueueReload(cfg) } }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L117:
for cfg := range watchReloadCh { enqueueReload(cfg) }- What: Iterates over a collection.
- Why: Processes multiple elements with the same logic.
- How: Executes a
for ... rangeloop. - Nested steps:
- L118:
enqueueReload(cfg)- What: Calls enqueueReload.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L118:
- L117:
- L116:
- L107:
- L122:
defer func() { if watchCancel != nil { watchCancel() } }()- What: Defers a call for cleanup.
- Why: Ensures the deferred action runs even on early returns.
- How: Schedules the call to run when the surrounding function returns.
- Nested steps:
- L122:
func() { if watchCancel != nil { watchCancel() } }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L123:
if watchCancel != nil { watchCancel() }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L124:
watchCancel()- What: Calls watchCancel.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L124:
- L123:
- L122:
- L128:
runCtx, runCancel := context.WithCancel(ctx)- What: Defines runCtx, runCancel.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L129:
runDone := make(chan error, 1)- What: Defines runDone.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L130:
go func() { runDone <- rt.Run(runCtx) }()- What: Starts a goroutine.
- Why: Runs work concurrently.
- How: Invokes the function call asynchronously using
go. - Nested steps:
- L130:
func() { runDone <- rt.Run(runCtx) }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L131:
runDone <- rt.Run(runCtx)- What: Sends a value on a channel.
- Why: Communicates with another goroutine.
- How: Executes a channel send operation.
- L131:
- L130:
- L134:
for { select { case err := <-runDone: runCancel() if err != nil && !errors.Is(err, context.Canceled) { return err } return nil case cfg := …- What: Runs a loop.
- Why: Repeats logic until a condition is met or the loop terminates.
- How: Executes a
forloop statement. - Nested steps:
- L135:
select { case err := <-runDone: runCancel() if err != nil && !errors.Is(err, context.Canceled) { return err } return nil case cfg := <-relo…- What: Selects among concurrent operations.
- Why: Coordinates channel operations without blocking incorrectly.
- How: Executes a
selectstatement and runs one ready case. - Nested steps:
- L136:
case err := <-runDone:- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- Nested steps:
- L137:
runCancel()- What: Calls runCancel.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L138:
if err != nil && !errors.Is(err, context.Canceled) { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L139:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L139:
- L141:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L137:
- L142:
case cfg := <-reloadRequests:- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- Nested steps:
- L143:
runCancel()- What: Calls runCancel.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L144:
if err := <-runDone; err != nil && !errors.Is(err, context.Canceled) { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L144:
err := <-runDone- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L145:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L144:
- L147:
if err := rt.Reload(cfg); err != nil { return fmt.Errorf("reload config: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L147:
err := rt.Reload(cfg)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L148:
return fmt.Errorf("reload config: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L147:
- L150:
runCtx, runCancel = context.WithCancel(ctx)- What: Assigns runCtx, runCancel.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L151:
runDone = make(chan error, 1)- What: Assigns runDone.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L152:
go func() { runDone <- rt.Run(runCtx) }()- What: Starts a goroutine.
- Why: Runs work concurrently.
- How: Invokes the function call asynchronously using
go. - Nested steps:
- L152:
func() { runDone <- rt.Run(runCtx) }- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L153:
runDone <- rt.Run(runCtx)- What: Sends a value on a channel.
- Why: Communicates with another goroutine.
- How: Executes a channel send operation.
- L153:
- L152:
- L155:
log.Printf("configuration reloaded")- What: Calls log.Printf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L143:
- L156:
case err, ok := <-watchErrCh:- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- Nested steps:
- L157:
if !ok { watchErrCh = nil continue }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L158:
watchErrCh = nil- What: Assigns watchErrCh.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L159:
continue- What: Executes a statement.
- Why: Advances the function logic.
- How: Runs this statement as part of the function body.
- L158:
- L161:
if err != nil { log.Printf("config watch error: %v", err) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L162:
log.Printf("config watch error: %v", err)- What: Calls log.Printf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L162:
- L157:
- L164:
case <-ctx.Done():- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- Nested steps:
- L165:
runCancel()- What: Calls runCancel.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L165:
- L136:
- L135:
validateCommand
What: Implements apigw validate to check config validity without starting the server.
Why: Useful in CI and in deployment pipelines to fail fast before rollout.
How: Loads config via gatewayconfig.Load (optionally with --config) and prints a success message on completion.
func validateCommand(args []string) error {
fs := flag.NewFlagSet("validate", flag.ExitOnError)
configPath := fs.String("config", "", "Path to gateway configuration file")
if err := fs.Parse(args); err != nil {
return err
}
opts := []gatewayconfig.Option{}
if *configPath != "" {
opts = append(opts, gatewayconfig.WithPath(*configPath))
}
if _, err := gatewayconfig.Load(opts...); err != nil {
return fmt.Errorf("validate config: %w", err)
}
fmt.Println("configuration valid")
return nil
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L171:
fs := flag.NewFlagSet("validate", flag.ExitOnError)- What: Defines fs.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L172:
configPath := fs.String("config", "", "Path to gateway configuration file")- What: Defines configPath.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L173:
if err := fs.Parse(args); err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L173:
err := fs.Parse(args)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L174:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L173:
- L177:
opts := []gatewayconfig.Option{}- What: Defines opts.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L178:
if *configPath != "" { opts = append(opts, gatewayconfig.WithPath(*configPath)) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L179:
opts = append(opts, gatewayconfig.WithPath(*configPath))- What: Assigns opts.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L179:
- L182:
if _, err := gatewayconfig.Load(opts...); err != nil { return fmt.Errorf("validate config: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L182:
_, err := gatewayconfig.Load(opts...)- What: Defines _, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L183:
return fmt.Errorf("validate config: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L182:
- L186:
fmt.Println("configuration valid")- What: Calls fmt.Println.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L187:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
initCommand
What: Implements apigw init to write a sample configuration file.
Why: Reduces friction for first-time setup and local development.
How: Writes sampleConfigYAML to --path (default apigw.yaml) and refuses to overwrite unless --force is set.
func initCommand(args []string) error {
fs := flag.NewFlagSet("init", flag.ExitOnError)
outputPath := fs.String("path", "apigw.yaml", "Destination path for generated config")
force := fs.Bool("force", false, "Overwrite existing file")
if err := fs.Parse(args); err != nil {
return err
}
if !*force {
if _, err := os.Stat(*outputPath); err == nil {
return fmt.Errorf("config file %s already exists (use --force to overwrite)", *outputPath)
}
}
if err := os.WriteFile(*outputPath, []byte(sampleConfigYAML), 0o644); err != nil {
return fmt.Errorf("write config: %w", err)
}
fmt.Printf("configuration written to %s\n", *outputPath)
return nil
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L191:
fs := flag.NewFlagSet("init", flag.ExitOnError)- What: Defines fs.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L192:
outputPath := fs.String("path", "apigw.yaml", "Destination path for generated config")- What: Defines outputPath.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L193:
force := fs.Bool("force", false, "Overwrite existing file")- What: Defines force.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L194:
if err := fs.Parse(args); err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L194:
err := fs.Parse(args)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L195:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L194:
- L198:
if !*force { if _, err := os.Stat(*outputPath); err == nil { return fmt.Errorf("config file %s already exists (use --force to overwrite)", …- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L199:
if _, err := os.Stat(*outputPath); err == nil { return fmt.Errorf("config file %s already exists (use --force to overwrite)", *outputPath) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L199:
_, err := os.Stat(*outputPath)- What: Defines _, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L200:
return fmt.Errorf("config file %s already exists (use --force to overwrite)", *outputPath)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L199:
- L199:
- L204:
if err := os.WriteFile(*outputPath, []byte(sampleConfigYAML), 0o644); err != nil { return fmt.Errorf("write config: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L204:
err := os.WriteFile(*outputPath, []byte(sampleConfigYAML), 0o644)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L205:
return fmt.Errorf("write config: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L204:
- L208:
fmt.Printf("configuration written to %s\n", *outputPath)- What: Calls fmt.Printf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L209:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
usage
What: Prints CLI usage text.
Why: Provides a quick help message when the CLI is invoked incorrectly.
How: Writes a static usage block to stderr.
func usage() {
fmt.Fprintf(os.Stderr, "Usage: apigw <command> [options]\n")
fmt.Fprintf(os.Stderr, "Commands:\n")
fmt.Fprintf(os.Stderr, " run Start the gateway using the provided config\n")
fmt.Fprintf(os.Stderr, " validate Validate configuration without starting the gateway\n")
fmt.Fprintf(os.Stderr, " init Generate a config skeleton\n")
fmt.Fprintf(os.Stderr, " daemon Manage the gateway as a background process\n")
fmt.Fprintf(os.Stderr, " admin Invoke admin control-plane endpoints (status/reload)\n")
fmt.Fprintf(os.Stderr, " convert-env Snapshot environment variables into a YAML config\n")
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L213:
fmt.Fprintf(os.Stderr, "Usage: apigw <command> [options]\n")- What: Calls fmt.Fprintf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L214:
fmt.Fprintf(os.Stderr, "Commands:\n")- What: Calls fmt.Fprintf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L215:
fmt.Fprintf(os.Stderr, " run Start the gateway using the provided config\n")- What: Calls fmt.Fprintf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L216:
fmt.Fprintf(os.Stderr, " validate Validate configuration without starting the gateway\n")- What: Calls fmt.Fprintf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L217:
fmt.Fprintf(os.Stderr, " init Generate a config skeleton\n")- What: Calls fmt.Fprintf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L218:
fmt.Fprintf(os.Stderr, " daemon Manage the gateway as a background process\n")- What: Calls fmt.Fprintf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L219:
fmt.Fprintf(os.Stderr, " admin Invoke admin control-plane endpoints (status/reload)\n")- What: Calls fmt.Fprintf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L220:
fmt.Fprintf(os.Stderr, " convert-env Snapshot environment variables into a YAML config\n")- What: Calls fmt.Fprintf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
daemonCommand
What: Implements apigw daemon subcommand dispatch (start/stop/status).
Why: Groups daemon lifecycle operations under a single top-level command.
How: Selects a subcommand (default start) and delegates to daemonStart, daemonStop, or daemonStatus.
func daemonCommand(args []string) error {
subcommand := "start"
if len(args) > 0 && !strings.HasPrefix(args[0], "-") {
subcommand = args[0]
args = args[1:]
}
switch subcommand {
case "start":
return daemonStart(args)
case "stop":
return daemonStop(args)
case "status":
return daemonStatus(args)
default:
return fmt.Errorf("unknown daemon subcommand %q", subcommand)
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L226:
subcommand := "start"- What: Defines subcommand.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L227:
if len(args) > 0 && !strings.HasPrefix(args[0], "-") { subcommand = args[0] args = args[1:] }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L228:
subcommand = args[0]- What: Assigns subcommand.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L229:
args = args[1:]- What: Assigns args.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L228:
- L232:
switch subcommand { case "start": return daemonStart(args) case "stop": return daemonStop(args) case "status": return daemonStatus(args) de…- What: Selects a branch from multiple cases.
- Why: Keeps multi-case branching readable and explicit.
- How: Evaluates the switch expression and executes the first matching case.
- Nested steps:
- L233:
case "start":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L234:
return daemonStart(args)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L234:
- L235:
case "stop":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L236:
return daemonStop(args)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L236:
- L237:
case "status":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L238:
return daemonStatus(args)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L238:
- L239:
default:- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L240:
return fmt.Errorf("unknown daemon subcommand %q", subcommand)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L240:
- L233:
daemonStart
What: Starts the gateway daemon, optionally in background mode.
Why: Supports running the gateway as a managed process with PID/log files without requiring external tooling.
How: If --background and not already a child, spawns a child apigw daemon start process; otherwise calls gatewaydaemon.Run with config/pid/log options and a signal-cancelled context.
func daemonStart(args []string) error {
rawArgs := append([]string(nil), args...)
fs := flag.NewFlagSet("daemon start", flag.ExitOnError)
configPath := fs.String("config", "", "Path to gateway configuration file")
pidPath := fs.String("pid", "apigw.pid", "Path to write the PID file")
logPath := fs.String("log", "", "Path to write daemon logs")
background := fs.Bool("background", false, "Run the daemon in the background")
if err := fs.Parse(args); err != nil {
return err
}
isChild := os.Getenv(daemonChildEnv) == "1"
if *background && !isChild {
childArgs := []string{"daemon", "start"}
for _, arg := range rawArgs {
if strings.HasPrefix(arg, "--background") {
continue
}
childArgs = append(childArgs, arg)
}
cmd := exec.Command(os.Args[0], childArgs...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = append(os.Environ(), daemonChildEnv+"=1")
if err := cmd.Start(); err != nil {
return fmt.Errorf("start background daemon: %w", err)
}
fmt.Fprintf(os.Stdout, "daemon started (pid %d)\n", cmd.Process.Pid)
return nil
}
os.Unsetenv(daemonChildEnv)
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()
options := gatewaydaemon.Options{
ConfigPath: *configPath,
PIDFile: *pidPath,
LogFile: *logPath,
}
return gatewaydaemon.Run(ctx, options)
}
Walkthrough
Expand walkthrough (30 steps)
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L245:
rawArgs := append([]string(nil), args...)- What: Defines rawArgs.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L246:
fs := flag.NewFlagSet("daemon start", flag.ExitOnError)- What: Defines fs.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L247:
configPath := fs.String("config", "", "Path to gateway configuration file")- What: Defines configPath.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L248:
pidPath := fs.String("pid", "apigw.pid", "Path to write the PID file")- What: Defines pidPath.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L249:
logPath := fs.String("log", "", "Path to write daemon logs")- What: Defines logPath.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L250:
background := fs.Bool("background", false, "Run the daemon in the background")- What: Defines background.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L251:
if err := fs.Parse(args); err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L251:
err := fs.Parse(args)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L252:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L251:
- L255:
isChild := os.Getenv(daemonChildEnv) == "1"- What: Defines isChild.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L256:
if *background && !isChild { childArgs := []string{"daemon", "start"} for _, arg := range rawArgs { if strings.HasPrefix(arg, "--background…- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L257:
childArgs := []string{"daemon", "start"}- What: Defines childArgs.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L258:
for _, arg := range rawArgs { if strings.HasPrefix(arg, "--background") { continue } childArgs = append(childArgs, arg) }- What: Iterates over a collection.
- Why: Processes multiple elements with the same logic.
- How: Executes a
for ... rangeloop. - Nested steps:
- L259:
if strings.HasPrefix(arg, "--background") { continue }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L260:
continue- What: Executes a statement.
- Why: Advances the function logic.
- How: Runs this statement as part of the function body.
- L260:
- L262:
childArgs = append(childArgs, arg)- What: Assigns childArgs.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L259:
- L264:
cmd := exec.Command(os.Args[0], childArgs...)- What: Defines cmd.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L265:
cmd.Stdout = os.Stdout- What: Assigns cmd.Stdout.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L266:
cmd.Stderr = os.Stderr- What: Assigns cmd.Stderr.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L267:
cmd.Env = append(os.Environ(), daemonChildEnv+"=1")- What: Assigns cmd.Env.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L268:
if err := cmd.Start(); err != nil { return fmt.Errorf("start background daemon: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L268:
err := cmd.Start()- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L269:
return fmt.Errorf("start background daemon: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L268:
- L271:
fmt.Fprintf(os.Stdout, "daemon started (pid %d)\n", cmd.Process.Pid)- What: Calls fmt.Fprintf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L272:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L257:
- L275:
os.Unsetenv(daemonChildEnv)- What: Calls os.Unsetenv.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L276:
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)- What: Defines ctx, cancel.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L277:
defer cancel()- What: Defers a call for cleanup.
- Why: Ensures the deferred action runs even on early returns.
- How: Schedules the call to run when the surrounding function returns.
- L279:
options := gatewaydaemon.Options{ ConfigPath: *configPath, PIDFile: *pidPath, LogFile: *logPath, }- What: Defines options.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L285:
return gatewaydaemon.Run(ctx, options)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
daemonStop
What: Stops the daemon process by sending a signal and waiting for exit.
Why: Provides a controlled shutdown path and cleans up stale PID files.
How: Parses a signal, calls gatewaydaemon.Stop, then polls gatewaydaemon.Status until the process exits or the wait timeout expires.
func daemonStop(args []string) error {
fs := flag.NewFlagSet("daemon stop", flag.ExitOnError)
pidPath := fs.String("pid", "apigw.pid", "Path to PID file")
signalName := fs.String("signal", "SIGTERM", "Signal to send (name or number)")
wait := fs.Duration("wait", 5*time.Second, "Time to wait for shutdown")
if err := fs.Parse(args); err != nil {
return err
}
sig, err := parseSignal(*signalName)
if err != nil {
return err
}
status, err := gatewaydaemon.Stop(*pidPath, sig)
if errors.Is(err, os.ErrNotExist) {
fmt.Fprintln(os.Stdout, "daemon not running (no pid file)")
return nil
}
if err != nil {
return fmt.Errorf("stop daemon: %w", err)
}
if !status.Running {
fmt.Fprintln(os.Stdout, "daemon already stopped")
_ = os.Remove(*pidPath)
return nil
}
deadline := time.Now().Add(*wait)
waitDur := *wait
for {
time.Sleep(200 * time.Millisecond)
st, err := gatewaydaemon.Status(*pidPath)
if errors.Is(err, os.ErrNotExist) {
fmt.Fprintln(os.Stdout, "daemon stopped")
_ = os.Remove(*pidPath)
return nil
}
if err != nil {
return fmt.Errorf("check status: %w", err)
}
if !st.Running {
fmt.Fprintln(os.Stdout, "daemon stopped")
_ = os.Remove(*pidPath)
return nil
}
if time.Now().After(deadline) {
return fmt.Errorf("daemon pid %d did not stop within %s", st.PID, waitDur)
}
}
}
Walkthrough
Expand walkthrough (37 steps)
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L289:
fs := flag.NewFlagSet("daemon stop", flag.ExitOnError)- What: Defines fs.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L290:
pidPath := fs.String("pid", "apigw.pid", "Path to PID file")- What: Defines pidPath.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L291:
signalName := fs.String("signal", "SIGTERM", "Signal to send (name or number)")- What: Defines signalName.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L292:
wait := fs.Duration("wait", 5*time.Second, "Time to wait for shutdown")- What: Defines wait.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L293:
if err := fs.Parse(args); err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L293:
err := fs.Parse(args)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L294:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L293:
- L297:
sig, err := parseSignal(*signalName)- What: Defines sig, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L298:
if err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L299:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L299:
- L302:
status, err := gatewaydaemon.Stop(*pidPath, sig)- What: Defines status, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L303:
if errors.Is(err, os.ErrNotExist) { fmt.Fprintln(os.Stdout, "daemon not running (no pid file)") return nil }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L304:
fmt.Fprintln(os.Stdout, "daemon not running (no pid file)")- What: Calls fmt.Fprintln.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L305:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L304:
- L307:
if err != nil { return fmt.Errorf("stop daemon: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L308:
return fmt.Errorf("stop daemon: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L308:
- L311:
if !status.Running { fmt.Fprintln(os.Stdout, "daemon already stopped") _ = os.Remove(*pidPath) return nil }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L312:
fmt.Fprintln(os.Stdout, "daemon already stopped")- What: Calls fmt.Fprintln.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L313:
_ = os.Remove(*pidPath)- What: Assigns _.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L314:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L312:
- L317:
deadline := time.Now().Add(*wait)- What: Defines deadline.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L318:
waitDur := *wait- What: Defines waitDur.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L319:
for { time.Sleep(200 * time.Millisecond) st, err := gatewaydaemon.Status(*pidPath) if errors.Is(err, os.ErrNotExist) { fmt.Fprintln(os.Stdo…- What: Runs a loop.
- Why: Repeats logic until a condition is met or the loop terminates.
- How: Executes a
forloop statement. - Nested steps:
- L320:
time.Sleep(200 * time.Millisecond)- What: Calls time.Sleep.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L321:
st, err := gatewaydaemon.Status(*pidPath)- What: Defines st, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L322:
if errors.Is(err, os.ErrNotExist) { fmt.Fprintln(os.Stdout, "daemon stopped") _ = os.Remove(*pidPath) return nil }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L323:
fmt.Fprintln(os.Stdout, "daemon stopped")- What: Calls fmt.Fprintln.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L324:
_ = os.Remove(*pidPath)- What: Assigns _.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L325:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L323:
- L327:
if err != nil { return fmt.Errorf("check status: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L328:
return fmt.Errorf("check status: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L328:
- L330:
if !st.Running { fmt.Fprintln(os.Stdout, "daemon stopped") _ = os.Remove(*pidPath) return nil }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L331:
fmt.Fprintln(os.Stdout, "daemon stopped")- What: Calls fmt.Fprintln.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L332:
_ = os.Remove(*pidPath)- What: Assigns _.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L333:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L331:
- L335:
if time.Now().After(deadline) { return fmt.Errorf("daemon pid %d did not stop within %s", st.PID, waitDur) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L336:
return fmt.Errorf("daemon pid %d did not stop within %s", st.PID, waitDur)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L336:
- L320:
daemonStatus
What: Reports daemon status based on the PID file.
Why: Allows scripts and operators to check whether the managed process is running.
How: Calls gatewaydaemon.Status and prints daemon running, daemon stopped, or daemon not running depending on the PID/state.
func daemonStatus(args []string) error {
fs := flag.NewFlagSet("daemon status", flag.ExitOnError)
pidPath := fs.String("pid", "apigw.pid", "Path to PID file")
if err := fs.Parse(args); err != nil {
return err
}
status, err := gatewaydaemon.Status(*pidPath)
if err != nil {
return fmt.Errorf("status: %w", err)
}
if status.PID == 0 {
fmt.Fprintln(os.Stdout, "daemon not running")
return nil
}
if status.Running {
fmt.Fprintf(os.Stdout, "daemon running (pid %d)\n", status.PID)
} else {
fmt.Fprintf(os.Stdout, "daemon stopped (stale pid %d)\n", status.PID)
}
return nil
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L342:
fs := flag.NewFlagSet("daemon status", flag.ExitOnError)- What: Defines fs.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L343:
pidPath := fs.String("pid", "apigw.pid", "Path to PID file")- What: Defines pidPath.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L344:
if err := fs.Parse(args); err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L344:
err := fs.Parse(args)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L345:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L344:
- L348:
status, err := gatewaydaemon.Status(*pidPath)- What: Defines status, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L349:
if err != nil { return fmt.Errorf("status: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L350:
return fmt.Errorf("status: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L350:
- L352:
if status.PID == 0 { fmt.Fprintln(os.Stdout, "daemon not running") return nil }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L353:
fmt.Fprintln(os.Stdout, "daemon not running")- What: Calls fmt.Fprintln.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L354:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L353:
- L356:
if status.Running { fmt.Fprintf(os.Stdout, "daemon running (pid %d)\n", status.PID) } else { fmt.Fprintf(os.Stdout, "daemon stopped (stale …- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L357:
fmt.Fprintf(os.Stdout, "daemon running (pid %d)\n", status.PID)- What: Calls fmt.Fprintf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L359:
fmt.Fprintf(os.Stdout, "daemon stopped (stale pid %d)\n", status.PID)- What: Calls fmt.Fprintf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L357:
- L361:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
parseSignal
What: Parses a signal name or number into a syscall.Signal.
Why: Allows daemon stop to accept both human-friendly names and numeric values.
How: Accepts integers and a small set of common names (TERM, KILL, INT, QUIT), returning an error for unsupported values.
func parseSignal(value string) (syscall.Signal, error) {
if value == "" {
return syscall.SIGTERM, nil
}
if n, err := strconv.Atoi(value); err == nil {
return syscall.Signal(n), nil
}
switch strings.ToUpper(value) {
case "TERM", "SIGTERM":
return syscall.SIGTERM, nil
case "KILL", "SIGKILL":
return syscall.SIGKILL, nil
case "INT", "SIGINT":
return syscall.SIGINT, nil
case "QUIT", "SIGQUIT":
return syscall.SIGQUIT, nil
default:
return 0, fmt.Errorf("unsupported signal %q", value)
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L365:
if value == "" { return syscall.SIGTERM, nil }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L366:
return syscall.SIGTERM, nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L366:
- L368:
if n, err := strconv.Atoi(value); err == nil { return syscall.Signal(n), nil }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L368:
n, err := strconv.Atoi(value)- What: Defines n, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L369:
return syscall.Signal(n), nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L368:
- L372:
switch strings.ToUpper(value) { case "TERM", "SIGTERM": return syscall.SIGTERM, nil case "KILL", "SIGKILL": return syscall.SIGKILL, nil cas…- What: Selects a branch from multiple cases.
- Why: Keeps multi-case branching readable and explicit.
- How: Evaluates the switch expression and executes the first matching case.
- Nested steps:
- L373:
case "TERM", "SIGTERM":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L374:
return syscall.SIGTERM, nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L374:
- L375:
case "KILL", "SIGKILL":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L376:
return syscall.SIGKILL, nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L376:
- L377:
case "INT", "SIGINT":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L378:
return syscall.SIGINT, nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L378:
- L379:
case "QUIT", "SIGQUIT":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L380:
return syscall.SIGQUIT, nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L380:
- L381:
default:- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L382:
return 0, fmt.Errorf("unsupported signal %q", value)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L382:
- L373:
adminCommand
What: Implements the apigw admin subcommand (status/config/reload).
Why: Provides a simple way to query or trigger control-plane behavior from scripts and terminals.
How: Parses flags (base URL, token, timeout) and dispatches to adminGET or adminPOST based on subcommand.
func adminCommand(args []string) error {
subcommand := "status"
if len(args) > 0 && !strings.HasPrefix(args[0], "-") {
subcommand = args[0]
args = args[1:]
}
fs := flag.NewFlagSet("admin "+subcommand, flag.ExitOnError)
baseURL := fs.String("url", "http://127.0.0.1:9090", "Base URL for the admin server")
token := fs.String("token", "", "Bearer token for admin requests")
timeout := fs.Duration("timeout", 5*time.Second, "HTTP request timeout")
if err := fs.Parse(args); err != nil {
return err
}
client := &http.Client{Timeout: *timeout}
base := strings.TrimRight(*baseURL, "/")
switch subcommand {
case "status":
return adminGET(client, base+"/__admin/status", *token)
case "config":
return adminGET(client, base+"/__admin/config", *token)
case "reload":
return adminPOST(client, base+"/__admin/reload", *token)
default:
return fmt.Errorf("unknown admin subcommand %q", subcommand)
}
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L387:
subcommand := "status"- What: Defines subcommand.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L388:
if len(args) > 0 && !strings.HasPrefix(args[0], "-") { subcommand = args[0] args = args[1:] }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L389:
subcommand = args[0]- What: Assigns subcommand.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L390:
args = args[1:]- What: Assigns args.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L389:
- L393:
fs := flag.NewFlagSet("admin "+subcommand, flag.ExitOnError)- What: Defines fs.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L394:
baseURL := fs.String("url", "http://127.0.0.1:9090", "Base URL for the admin server")- What: Defines baseURL.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L395:
token := fs.String("token", "", "Bearer token for admin requests")- What: Defines token.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L396:
timeout := fs.Duration("timeout", 5*time.Second, "HTTP request timeout")- What: Defines timeout.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L397:
if err := fs.Parse(args); err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L397:
err := fs.Parse(args)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L398:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L397:
- L401:
client := &http.Client{Timeout: *timeout}- What: Defines client.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L402:
base := strings.TrimRight(*baseURL, "/")- What: Defines base.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L404:
switch subcommand { case "status": return adminGET(client, base+"/__admin/status", *token) case "config": return adminGET(client, base+"/__…- What: Selects a branch from multiple cases.
- Why: Keeps multi-case branching readable and explicit.
- How: Evaluates the switch expression and executes the first matching case.
- Nested steps:
- L405:
case "status":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L406:
return adminGET(client, base+"/__admin/status", *token)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L406:
- L407:
case "config":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L408:
return adminGET(client, base+"/__admin/config", *token)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L408:
- L409:
case "reload":- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L410:
return adminPOST(client, base+"/__admin/reload", *token)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L410:
- L411:
default:- What: Selects a switch case.
- Why: Makes multi-branch control flow explicit and readable.
- How: Runs this case body when the switch value matches (or when default is selected).
- Nested steps:
- L412:
return fmt.Errorf("unknown admin subcommand %q", subcommand)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L412:
- L405:
adminGET
What: Performs an admin GET request and prints the JSON response body.
Why: Shared helper for admin status and admin config.
How: Builds an HTTP request, optionally sets bearer token header, checks for 200 OK, and prints the response body.
func adminGET(client *http.Client, url, token string) error {
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return err
}
if token != "" {
req.Header.Set("Authorization", "Bearer "+token)
}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("admin request failed: %s", strings.TrimSpace(string(body)))
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
fmt.Println(string(body))
return nil
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L417:
req, err := http.NewRequest(http.MethodGet, url, nil)- What: Defines req, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L418:
if err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L419:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L419:
- L421:
if token != "" { req.Header.Set("Authorization", "Bearer "+token) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L422:
req.Header.Set("Authorization", "Bearer "+token)- What: Calls req.Header.Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L422:
- L424:
resp, err := client.Do(req)- What: Defines resp, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L425:
if err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L426:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L426:
- L428:
defer resp.Body.Close()- What: Defers a call for cleanup.
- Why: Ensures the deferred action runs even on early returns.
- How: Schedules the call to run when the surrounding function returns.
- L429:
if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) return fmt.Errorf("admin request failed: %s", strings.TrimSpace(stri…- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L430:
body, _ := io.ReadAll(resp.Body)- What: Defines body, _.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L431:
return fmt.Errorf("admin request failed: %s", strings.TrimSpace(string(body)))- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L430:
- L433:
body, err := io.ReadAll(resp.Body)- What: Defines body, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L434:
if err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L435:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L435:
- L437:
fmt.Println(string(body))- What: Calls fmt.Println.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L438:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
adminPOST
What: Performs an admin POST request and prints the response body (or a fallback message).
Why: Shared helper for admin reload.
How: Builds an HTTP POST request, optionally sets bearer token header, checks for 202 Accepted, and prints the response body or "reload requested".
func adminPOST(client *http.Client, url, token string) error {
req, err := http.NewRequest(http.MethodPost, url, nil)
if err != nil {
return err
}
if token != "" {
req.Header.Set("Authorization", "Bearer "+token)
}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusAccepted {
body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("admin reload failed: %s", strings.TrimSpace(string(body)))
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
if len(strings.TrimSpace(string(body))) > 0 {
fmt.Println(string(body))
} else {
fmt.Println("reload requested")
}
return nil
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L442:
req, err := http.NewRequest(http.MethodPost, url, nil)- What: Defines req, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L443:
if err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L444:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L444:
- L446:
if token != "" { req.Header.Set("Authorization", "Bearer "+token) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L447:
req.Header.Set("Authorization", "Bearer "+token)- What: Calls req.Header.Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L447:
- L449:
resp, err := client.Do(req)- What: Defines resp, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L450:
if err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L451:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L451:
- L453:
defer resp.Body.Close()- What: Defers a call for cleanup.
- Why: Ensures the deferred action runs even on early returns.
- How: Schedules the call to run when the surrounding function returns.
- L454:
if resp.StatusCode != http.StatusAccepted { body, _ := io.ReadAll(resp.Body) return fmt.Errorf("admin reload failed: %s", strings.TrimSpace…- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L455:
body, _ := io.ReadAll(resp.Body)- What: Defines body, _.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L456:
return fmt.Errorf("admin reload failed: %s", strings.TrimSpace(string(body)))- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L455:
- L458:
body, err := io.ReadAll(resp.Body)- What: Defines body, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L459:
if err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L460:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L460:
- L462:
if len(strings.TrimSpace(string(body))) > 0 { fmt.Println(string(body)) } else { fmt.Println("reload requested") }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L463:
fmt.Println(string(body))- What: Calls fmt.Println.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L465:
fmt.Println("reload requested")- What: Calls fmt.Println.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L463:
- L467:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
watchConfig
What: Watches a config file for changes and emits reloaded gatewayconfig.Config values.
Why: Enables apigw run --watch hot reloads without external tooling.
How: Creates an fsnotify watcher on the config directory, debounces write/create/rename events, reloads config via gatewayconfig.Load, and returns channels for configs and errors plus a cancel function.
func watchConfig(parent context.Context, path string, opts []gatewayconfig.Option) (<-chan gatewayconfig.Config, <-chan error, context.CancelFunc, error) {
absPath, err := filepath.Abs(path)
if err != nil {
return nil, nil, nil, fmt.Errorf("resolve config path: %w", err)
}
watcher, err := fsnotify.NewWatcher()
if err != nil {
return nil, nil, nil, err
}
dir := filepath.Dir(absPath)
if err := watcher.Add(dir); err != nil {
watcher.Close()
return nil, nil, nil, fmt.Errorf("watch directory: %w", err)
}
ctx, cancel := context.WithCancel(parent)
reloadCh := make(chan gatewayconfig.Config)
errCh := make(chan error, 1)
go func() {
defer close(reloadCh)
defer close(errCh)
defer watcher.Close()
var debounce <-chan time.Time
for {
select {
case <-ctx.Done():
return
case evt, ok := <-watcher.Events:
if !ok {
return
}
if !targetsFile(evt.Name, absPath) {
continue
}
if evt.Op&(fsnotify.Write|fsnotify.Create|fsnotify.Rename) == 0 {
continue
}
debounce = time.After(200 * time.Millisecond)
case <-debounce:
cfg, err := gatewayconfig.Load(opts...)
if err != nil {
errCh <- err
debounce = nil
continue
}
select {
case reloadCh <- cfg:
case <-ctx.Done():
}
debounce = nil
case err, ok := <-watcher.Errors:
if !ok {
return
}
errCh <- err
}
}
}()
return reloadCh, errCh, cancel, nil
}
Walkthrough
Expand walkthrough (47 steps)
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L471:
absPath, err := filepath.Abs(path)- What: Defines absPath, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L472:
if err != nil { return nil, nil, nil, fmt.Errorf("resolve config path: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L473:
return nil, nil, nil, fmt.Errorf("resolve config path: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L473:
- L476:
watcher, err := fsnotify.NewWatcher()- What: Defines watcher, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L477:
if err != nil { return nil, nil, nil, err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L478:
return nil, nil, nil, err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L478:
- L480:
dir := filepath.Dir(absPath)- What: Defines dir.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L481:
if err := watcher.Add(dir); err != nil { watcher.Close() return nil, nil, nil, fmt.Errorf("watch directory: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L481:
err := watcher.Add(dir)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L482:
watcher.Close()- What: Calls watcher.Close.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L483:
return nil, nil, nil, fmt.Errorf("watch directory: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L481:
- L486:
ctx, cancel := context.WithCancel(parent)- What: Defines ctx, cancel.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L487:
reloadCh := make(chan gatewayconfig.Config)- What: Defines reloadCh.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L488:
errCh := make(chan error, 1)- What: Defines errCh.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L490:
go func() { defer close(reloadCh) defer close(errCh) defer watcher.Close() var debounce <-chan time.Time for { select { case <-ctx.Done(): …- What: Starts a goroutine.
- Why: Runs work concurrently.
- How: Invokes the function call asynchronously using
go. - Nested steps:
- L490:
func() { defer close(reloadCh) defer close(errCh) defer watcher.Close() var debounce <-chan time.Time for { select { case <-ctx.Done(): ret…- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L491:
defer close(reloadCh)- What: Defers a call for cleanup.
- Why: Ensures the deferred action runs even on early returns.
- How: Schedules the call to run when the surrounding function returns.
- L492:
defer close(errCh)- What: Defers a call for cleanup.
- Why: Ensures the deferred action runs even on early returns.
- How: Schedules the call to run when the surrounding function returns.
- L493:
defer watcher.Close()- What: Defers a call for cleanup.
- Why: Ensures the deferred action runs even on early returns.
- How: Schedules the call to run when the surrounding function returns.
- L495:
var debounce <-chan time.Time- What: Declares local names.
- Why: Introduces variables or types used later in the function.
- How: Executes a Go declaration statement inside the function body.
- L496:
for { select { case <-ctx.Done(): return case evt, ok := <-watcher.Events: if !ok { return } if !targetsFile(evt.Name, absPath) { continue …- What: Runs a loop.
- Why: Repeats logic until a condition is met or the loop terminates.
- How: Executes a
forloop statement. - Nested steps:
- L497:
select { case <-ctx.Done(): return case evt, ok := <-watcher.Events: if !ok { return } if !targetsFile(evt.Name, absPath) { continue } if e…- What: Selects among concurrent operations.
- Why: Coordinates channel operations without blocking incorrectly.
- How: Executes a
selectstatement and runs one ready case. - Nested steps:
- L498:
case <-ctx.Done():- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- Nested steps:
- L499:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L499:
- L500:
case evt, ok := <-watcher.Events:- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- Nested steps:
- L501:
if !ok { return }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L502:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L502:
- L504:
if !targetsFile(evt.Name, absPath) { continue }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L505:
continue- What: Executes a statement.
- Why: Advances the function logic.
- How: Runs this statement as part of the function body.
- L505:
- L507:
if evt.Op&(fsnotify.Write|fsnotify.Create|fsnotify.Rename) == 0 { continue }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L508:
continue- What: Executes a statement.
- Why: Advances the function logic.
- How: Runs this statement as part of the function body.
- L508:
- L510:
debounce = time.After(200 * time.Millisecond)- What: Assigns debounce.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L501:
- L511:
case <-debounce:- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- Nested steps:
- L512:
cfg, err := gatewayconfig.Load(opts...)- What: Defines cfg, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L513:
if err != nil { errCh <- err debounce = nil continue }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L514:
errCh <- err- What: Sends a value on a channel.
- Why: Communicates with another goroutine.
- How: Executes a channel send operation.
- L515:
debounce = nil- What: Assigns debounce.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L516:
continue- What: Executes a statement.
- Why: Advances the function logic.
- How: Runs this statement as part of the function body.
- L514:
- L518:
select { case reloadCh <- cfg: case <-ctx.Done(): }- What: Selects among concurrent operations.
- Why: Coordinates channel operations without blocking incorrectly.
- How: Executes a
selectstatement and runs one ready case. - Nested steps:
- L519:
case reloadCh <- cfg:- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- L520:
case <-ctx.Done():- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- L519:
- L522:
debounce = nil- What: Assigns debounce.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L512:
- L523:
case err, ok := <-watcher.Errors:- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- Nested steps:
- L524:
if !ok { return }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L525:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L525:
- L527:
errCh <- err- What: Sends a value on a channel.
- Why: Communicates with another goroutine.
- How: Executes a channel send operation.
- L524:
- L498:
- L497:
- L491:
- L490:
- L532:
return reloadCh, errCh, cancel, nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
convertEnvCommand
What: Implements apigw convert-env to snapshot the effective configuration into YAML.
Why: Helps migrate legacy env-driven deployments to YAML by producing a reproducible config file.
How: Loads config (optionally merging an input YAML first), marshals to YAML, and writes to stdout or an output path (with optional --force).
func convertEnvCommand(args []string) error {
fs := flag.NewFlagSet("convert-env", flag.ExitOnError)
configPath := fs.String("config", "", "Optional config file to merge before env overrides")
outputPath := fs.String("output", "", "Destination path for generated YAML (stdout when empty)")
force := fs.Bool("force", false, "Overwrite existing output file")
if err := fs.Parse(args); err != nil {
return err
}
opts := []gatewayconfig.Option{}
if strings.TrimSpace(*configPath) != "" {
opts = append(opts, gatewayconfig.WithPath(*configPath))
}
cfg, err := gatewayconfig.Load(opts...)
if err != nil {
return fmt.Errorf("load config from environment: %w", err)
}
data, err := yaml.Marshal(cfg)
if err != nil {
return fmt.Errorf("encode config: %w", err)
}
path := strings.TrimSpace(*outputPath)
if path == "" {
fmt.Print(string(data))
return nil
}
if !*force {
if _, err := os.Stat(path); err == nil {
return fmt.Errorf("output file %s already exists (use --force to overwrite)", path)
} else if err != nil && !errors.Is(err, os.ErrNotExist) {
return fmt.Errorf("stat output file: %w", err)
}
}
dir := filepath.Dir(path)
if dir != "." && dir != "" {
if err := os.MkdirAll(dir, 0o755); err != nil {
return fmt.Errorf("ensure output directory: %w", err)
}
}
if err := os.WriteFile(path, data, 0o644); err != nil {
return fmt.Errorf("write output file: %w", err)
}
fmt.Printf("configuration written to %s\n", path)
return nil
}
Walkthrough
Expand walkthrough (36 steps)
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L536:
fs := flag.NewFlagSet("convert-env", flag.ExitOnError)- What: Defines fs.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L537:
configPath := fs.String("config", "", "Optional config file to merge before env overrides")- What: Defines configPath.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L538:
outputPath := fs.String("output", "", "Destination path for generated YAML (stdout when empty)")- What: Defines outputPath.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L539:
force := fs.Bool("force", false, "Overwrite existing output file")- What: Defines force.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L540:
if err := fs.Parse(args); err != nil { return err }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L540:
err := fs.Parse(args)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L541:
return err- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L540:
- L544:
opts := []gatewayconfig.Option{}- What: Defines opts.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L545:
if strings.TrimSpace(*configPath) != "" { opts = append(opts, gatewayconfig.WithPath(*configPath)) }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L546:
opts = append(opts, gatewayconfig.WithPath(*configPath))- What: Assigns opts.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L546:
- L549:
cfg, err := gatewayconfig.Load(opts...)- What: Defines cfg, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L550:
if err != nil { return fmt.Errorf("load config from environment: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L551:
return fmt.Errorf("load config from environment: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L551:
- L554:
data, err := yaml.Marshal(cfg)- What: Defines data, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L555:
if err != nil { return fmt.Errorf("encode config: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L556:
return fmt.Errorf("encode config: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L556:
- L559:
path := strings.TrimSpace(*outputPath)- What: Defines path.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L560:
if path == "" { fmt.Print(string(data)) return nil }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L561:
fmt.Print(string(data))- What: Calls fmt.Print.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L562:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L561:
- L565:
if !*force { if _, err := os.Stat(path); err == nil { return fmt.Errorf("output file %s already exists (use --force to overwrite)", path) }…- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L566:
if _, err := os.Stat(path); err == nil { return fmt.Errorf("output file %s already exists (use --force to overwrite)", path) } else if err …- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L566:
_, err := os.Stat(path)- What: Defines _, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L567:
return fmt.Errorf("output file %s already exists (use --force to overwrite)", path)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L568:
if err != nil && !errors.Is(err, os.ErrNotExist) { return fmt.Errorf("stat output file: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L569:
return fmt.Errorf("stat output file: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L569:
- L566:
- L566:
- L573:
dir := filepath.Dir(path)- What: Defines dir.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L574:
if dir != "." && dir != "" { if err := os.MkdirAll(dir, 0o755); err != nil { return fmt.Errorf("ensure output directory: %w", err) } }- What: Branches conditionally.
- Why: Handles different execution paths based on runtime state.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L575:
if err := os.MkdirAll(dir, 0o755); err != nil { return fmt.Errorf("ensure output directory: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L575:
err := os.MkdirAll(dir, 0o755)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L576:
return fmt.Errorf("ensure output directory: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L575:
- L575:
- L580:
if err := os.WriteFile(path, data, 0o644); err != nil { return fmt.Errorf("write output file: %w", err) }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L580:
err := os.WriteFile(path, data, 0o644)- What: Defines err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L581:
return fmt.Errorf("write output file: %w", err)- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L580:
- L584:
fmt.Printf("configuration written to %s\n", path)- What: Calls fmt.Printf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L585:
return nil- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
targetsFile
What: Checks whether a filesystem watcher event refers to the target config file.
Why: fsnotify emits directory-level events; this filters down to the single config file we care about.
How: Resolves the event path to an absolute path and compares it to the expected absolute config path.
func targetsFile(eventPath, target string) bool {
if eventPath == "" {
return false
}
abs, err := filepath.Abs(eventPath)
if err != nil {
return false
}
return abs == target
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L589:
if eventPath == "" { return false }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L590:
return false- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L590:
- L592:
abs, err := filepath.Abs(eventPath)- What: Defines abs, err.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L593:
if err != nil { return false }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L594:
return false- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L594:
- L596:
return abs == target- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).