Files
vpp-maglev/cmd/client/main.go
T
pim d9a8ca6fb8 feat(maglevc): JSON output for all commands (-json)
Enable App.JSON and add -json on golang-cli v1.4.0, mirroring evpnc so
the two CLIs' JSON contract is identical: show/query -> data, set/action
-> {}, failure -> {"error": "..."}.

- show/query commands branch on cli.IsJSON() -> emit the protobuf via
  cli.EmitJSON; text keeps the tabwriter painters (which robot tests
  parse via show, not via setter output).
- action commands (pause/resume/enable/disable, set weight, sync,
  config reload) are now silent on success in text too — "we did what
  you asked" needs no confirmation — and print "{}" in JSON via wrapJSON.
- config check stays informative (it is a query): text "config ok" /
  error, JSON the CheckConfig report.
- errors: formatError returns {"error": "..."} in JSON mode.
- watch streams its own JSON events (no trailing {}).

Robot tests assert backend state via `show`, not setter stdout, so the
dropped confirmations don't affect them. Builds on linux and openbsd.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 23:31:21 +02:00

55 lines
1.9 KiB
Go

// SPDX-License-Identifier: Apache-2.0
// Command maglevc is the vpp-maglev CLI. It talks only to maglevd. With no
// arguments it starts an interactive shell (readline, tab-completion, '?' help,
// prefix abbreviation); with arguments it runs one command and exits. The
// command set is a single declarative tree (buildTree) -- dispatch, help, and
// completion are all derived from it, via the git.ipng.ch/ipng/golang-cli
// library.
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
cli "git.ipng.ch/ipng/golang-cli"
buildinfo "git.ipng.ch/ipng/vpp-maglev/cmd"
"git.ipng.ch/ipng/vpp-maglev/internal/grpcapi"
"git.ipng.ch/ipng/vpp-maglev/internal/netutil"
)
// defaultGRPCPort is the maglevd gRPC port (mirrors the server's -grpc-addr
// default), used when -server is given without an explicit ":<port>".
const defaultGRPCPort = "9090"
func main() {
(&cli.App[grpcapi.MaglevClient]{
Name: "maglevc",
Version: buildinfo.Version(),
Commit: buildinfo.Commit(),
Date: buildinfo.Date(),
Prompt: "maglev> ",
Root: buildTree(),
JSON: true, // commands render via cli.IsJSON() (see json.go)
DefaultServer: "localhost:9090",
ServerEnv: "MAGLEV_SERVER",
Connect: connect,
FormatError: formatError,
}).Main()
}
// connect dials maglevd and returns the gRPC client. App resolves -server (env
// MAGLEV_SERVER, default localhost:9090) and hands us the raw address; we ensure
// a port and dial insecure, mirroring maglevd's default transport.
func connect(_ context.Context, server string) (grpcapi.MaglevClient, func(), error) {
addr := netutil.EnsurePort(server, defaultGRPCPort)
conn, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return nil, nil, fmt.Errorf("connect %s: %w", addr, err)
}
return grpcapi.NewMaglevClient(conn), func() { _ = conn.Close() }, nil
}