mirror of
https://github.com/netbirdio/netbird.git
synced 2026-05-20 23:59:55 +00:00
[client] add new json flags
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/netbirdio/netbird/client/proto"
|
||||
nbstatus "github.com/netbirdio/netbird/client/status"
|
||||
)
|
||||
|
||||
var downCmd = &cobra.Command{
|
||||
@@ -44,7 +45,29 @@ var downCmd = &cobra.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Println("Disconnected")
|
||||
out := &nbstatus.DownOutput{Status: "Disconnected"}
|
||||
switch {
|
||||
case jsonFlag:
|
||||
s, err := out.JSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.Println(s)
|
||||
case yamlFlag:
|
||||
s, err := out.YAML()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.Print(s)
|
||||
default:
|
||||
cmd.Println(out.Status)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
downCmd.PersistentFlags().BoolVarP(&jsonFlag, "json", "j", false, "display command result in json format")
|
||||
downCmd.PersistentFlags().BoolVarP(&yamlFlag, "yaml", "y", false, "display command result in yaml format")
|
||||
downCmd.MarkFlagsMutuallyExclusive("json", "yaml")
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/netbirdio/netbird/client/internal/auth"
|
||||
"github.com/netbirdio/netbird/client/internal/profilemanager"
|
||||
"github.com/netbirdio/netbird/client/proto"
|
||||
nbstatus "github.com/netbirdio/netbird/client/status"
|
||||
"github.com/netbirdio/netbird/client/system"
|
||||
"github.com/netbirdio/netbird/util"
|
||||
)
|
||||
@@ -337,6 +338,11 @@ func foregroundGetTokenInfo(ctx context.Context, cmd *cobra.Command, config *pro
|
||||
}
|
||||
|
||||
func openURL(cmd *cobra.Command, verificationURIComplete, userCode string, noBrowser, showQR bool) {
|
||||
if jsonFlag || yamlFlag {
|
||||
emitSSOEvent(cmd, verificationURIComplete, userCode)
|
||||
return
|
||||
}
|
||||
|
||||
var codeMsg string
|
||||
if userCode != "" && !strings.Contains(verificationURIComplete, userCode) {
|
||||
codeMsg = fmt.Sprintf("and enter the code %s to authenticate.", userCode)
|
||||
@@ -366,6 +372,33 @@ func openURL(cmd *cobra.Command, verificationURIComplete, userCode string, noBro
|
||||
}
|
||||
}
|
||||
|
||||
// emitSSOEvent writes the verification URL/code as a structured event for
|
||||
// callers using --json or --yaml. The browser is intentionally not opened in
|
||||
// this mode since automation contexts (CI, scripts) typically run headless.
|
||||
func emitSSOEvent(cmd *cobra.Command, verificationURIComplete, userCode string) {
|
||||
event := &nbstatus.SSOEvent{
|
||||
Event: "sso_required",
|
||||
VerificationURIComplete: verificationURIComplete,
|
||||
UserCode: userCode,
|
||||
}
|
||||
if jsonFlag {
|
||||
s, err := event.JSON()
|
||||
if err != nil {
|
||||
log.Errorf("marshal sso event: %v", err)
|
||||
return
|
||||
}
|
||||
cmd.Println(s)
|
||||
return
|
||||
}
|
||||
s, err := event.YAML()
|
||||
if err != nil {
|
||||
log.Errorf("marshal sso event: %v", err)
|
||||
return
|
||||
}
|
||||
cmd.Print(s)
|
||||
cmd.Println("---")
|
||||
}
|
||||
|
||||
// isUnixRunningDesktop checks if a Linux OS is running desktop environment
|
||||
func isUnixRunningDesktop() bool {
|
||||
if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" {
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/netbirdio/netbird/client/internal/peer"
|
||||
"github.com/netbirdio/netbird/client/internal/profilemanager"
|
||||
"github.com/netbirdio/netbird/client/proto"
|
||||
nbstatus "github.com/netbirdio/netbird/client/status"
|
||||
"github.com/netbirdio/netbird/client/system"
|
||||
"github.com/netbirdio/netbird/shared/management/domain"
|
||||
"github.com/netbirdio/netbird/util"
|
||||
@@ -88,6 +89,9 @@ func init() {
|
||||
upCmd.PersistentFlags().StringVar(&profileName, profileNameFlag, "", profileNameDesc)
|
||||
upCmd.PersistentFlags().StringVarP(&configPath, "config", "c", "", "(DEPRECATED) NetBird config file location. ")
|
||||
|
||||
upCmd.PersistentFlags().BoolVarP(&jsonFlag, "json", "j", false, "display command result in json format")
|
||||
upCmd.PersistentFlags().BoolVarP(&yamlFlag, "yaml", "y", false, "display command result in yaml format")
|
||||
upCmd.MarkFlagsMutuallyExclusive("json", "yaml")
|
||||
}
|
||||
|
||||
func upFunc(cmd *cobra.Command, args []string) error {
|
||||
@@ -96,6 +100,10 @@ func upFunc(cmd *cobra.Command, args []string) error {
|
||||
|
||||
cmd.SetOut(cmd.OutOrStdout())
|
||||
|
||||
if (jsonFlag || yamlFlag) && foregroundMode {
|
||||
return fmt.Errorf("--json/--yaml is not supported with --foreground-mode; use daemon mode")
|
||||
}
|
||||
|
||||
err := util.InitLog(logLevel, util.LogConsole)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed initializing log %v", err)
|
||||
@@ -245,8 +253,10 @@ func runInDaemonMode(ctx context.Context, cmd *cobra.Command, pm *profilemanager
|
||||
|
||||
if status.Status == string(internal.StatusConnected) {
|
||||
if !profileSwitched {
|
||||
cmd.Println("Already connected")
|
||||
return nil
|
||||
return emitUpOutput(cmd, &nbstatus.UpOutput{
|
||||
Status: "already_connected",
|
||||
ProfileName: activeProf.Name,
|
||||
}, "Already connected")
|
||||
}
|
||||
|
||||
if _, err := client.Down(ctx, &proto.DownRequest{}); err != nil {
|
||||
@@ -273,7 +283,31 @@ func runInDaemonMode(ctx context.Context, cmd *cobra.Command, pm *profilemanager
|
||||
if err := doDaemonUp(ctx, cmd, client, pm, activeProf, customDNSAddressConverted, username.Username); err != nil {
|
||||
return fmt.Errorf("daemon up failed: %v", err)
|
||||
}
|
||||
cmd.Println("Connected")
|
||||
return emitUpOutput(cmd, &nbstatus.UpOutput{
|
||||
Status: "connected",
|
||||
ProfileName: activeProf.Name,
|
||||
}, "Connected")
|
||||
}
|
||||
|
||||
// emitUpOutput writes the result of an up command in the format requested by
|
||||
// the user (json, yaml, or human-readable text fallback).
|
||||
func emitUpOutput(cmd *cobra.Command, out *nbstatus.UpOutput, textFallback string) error {
|
||||
switch {
|
||||
case jsonFlag:
|
||||
s, err := out.JSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.Println(s)
|
||||
case yamlFlag:
|
||||
s, err := out.YAML()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.Print(s)
|
||||
default:
|
||||
cmd.Println(textFallback)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -384,6 +384,80 @@ func (o *OutputOverview) YAML() (string, error) {
|
||||
return string(yamlBytes), nil
|
||||
}
|
||||
|
||||
// DownOutput is the structured result of a `netbird down` command.
|
||||
type DownOutput struct {
|
||||
Status string `json:"status" yaml:"status"`
|
||||
}
|
||||
|
||||
// UpOutput is the final structured result of a `netbird up` command.
|
||||
type UpOutput struct {
|
||||
Status string `json:"status" yaml:"status"` // "connected" | "already_connected"
|
||||
ProfileName string `json:"profileName,omitempty" yaml:"profileName,omitempty"`
|
||||
}
|
||||
|
||||
// JSON returns the UpOutput as a JSON string.
|
||||
func (o *UpOutput) JSON() (string, error) {
|
||||
jsonBytes, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("json marshal failed")
|
||||
}
|
||||
return string(jsonBytes), err
|
||||
}
|
||||
|
||||
// YAML returns the UpOutput as a YAML string.
|
||||
func (o *UpOutput) YAML() (string, error) {
|
||||
yamlBytes, err := yaml.Marshal(o)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("yaml marshal failed")
|
||||
}
|
||||
return string(yamlBytes), nil
|
||||
}
|
||||
|
||||
// SSOEvent is emitted before the final UpOutput when interactive SSO is required.
|
||||
// It carries the verification URL and user code so callers can surface them
|
||||
// (e.g. to a Slack channel) without parsing free-form text.
|
||||
type SSOEvent struct {
|
||||
Event string `json:"event" yaml:"event"` // "sso_required"
|
||||
VerificationURIComplete string `json:"verificationUriComplete" yaml:"verificationUriComplete"`
|
||||
UserCode string `json:"userCode,omitempty" yaml:"userCode,omitempty"`
|
||||
}
|
||||
|
||||
// JSON returns the SSOEvent as a JSON string.
|
||||
func (e *SSOEvent) JSON() (string, error) {
|
||||
jsonBytes, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("json marshal failed")
|
||||
}
|
||||
return string(jsonBytes), err
|
||||
}
|
||||
|
||||
// YAML returns the SSOEvent as a YAML string.
|
||||
func (e *SSOEvent) YAML() (string, error) {
|
||||
yamlBytes, err := yaml.Marshal(e)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("yaml marshal failed")
|
||||
}
|
||||
return string(yamlBytes), nil
|
||||
}
|
||||
|
||||
// JSON returns the DownOutput as a JSON string.
|
||||
func (o *DownOutput) JSON() (string, error) {
|
||||
jsonBytes, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("json marshal failed")
|
||||
}
|
||||
return string(jsonBytes), err
|
||||
}
|
||||
|
||||
// YAML returns the DownOutput as a YAML string.
|
||||
func (o *DownOutput) YAML() (string, error) {
|
||||
yamlBytes, err := yaml.Marshal(o)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("yaml marshal failed")
|
||||
}
|
||||
return string(yamlBytes), nil
|
||||
}
|
||||
|
||||
// GeneralSummary returns a general summary of the status overview.
|
||||
func (o *OutputOverview) GeneralSummary(showURL bool, showRelays bool, showNameServers bool, showSSHSessions bool) string {
|
||||
var managementConnString string
|
||||
|
||||
Reference in New Issue
Block a user