2022-03-08 14:47:55 +01:00
package cmd
import (
"context"
2022-05-12 11:17:24 +02:00
"fmt"
2022-12-01 11:48:13 +01:00
"net"
"net/netip"
"strings"
2023-02-24 19:01:54 +01:00
"github.com/spf13/cobra"
"google.golang.org/grpc/status"
2022-12-01 11:48:13 +01:00
2022-07-05 19:47:50 +02:00
"github.com/netbirdio/netbird/client/internal"
"github.com/netbirdio/netbird/client/proto"
2025-02-21 16:29:21 +01:00
nbstatus "github.com/netbirdio/netbird/client/status"
2022-03-26 12:08:54 +01:00
"github.com/netbirdio/netbird/util"
2022-07-05 19:47:50 +02:00
)
2022-03-08 14:47:55 +01:00
2022-07-05 19:47:50 +02:00
var (
2023-12-14 11:18:43 +01:00
detailFlag bool
ipv4Flag bool
jsonFlag bool
yamlFlag bool
ipsFilter [ ] string
prefixNamesFilter [ ] string
statusFilter string
ipsFilterMap map [ string ] struct { }
prefixNamesFilterMap map [ string ] struct { }
2022-03-08 14:47:55 +01:00
)
var statusCmd = & cobra . Command {
Use : "status" ,
2022-05-22 18:53:47 +02:00
Short : "status of the Netbird Service" ,
2023-02-23 20:13:19 +01:00
RunE : statusFunc ,
}
2022-03-10 18:14:07 +01:00
2023-02-23 20:13:19 +01:00
func init ( ) {
ipsFilterMap = make ( map [ string ] struct { } )
2023-12-14 11:18:43 +01:00
prefixNamesFilterMap = make ( map [ string ] struct { } )
2023-02-23 20:13:19 +01:00
statusCmd . PersistentFlags ( ) . BoolVarP ( & detailFlag , "detail" , "d" , false , "display detailed status information in human-readable format" )
statusCmd . PersistentFlags ( ) . BoolVar ( & jsonFlag , "json" , false , "display detailed status information in json format" )
statusCmd . PersistentFlags ( ) . BoolVar ( & yamlFlag , "yaml" , false , "display detailed status information in yaml format" )
statusCmd . PersistentFlags ( ) . BoolVar ( & ipv4Flag , "ipv4" , false , "display only NetBird IPv4 of this peer, e.g., --ipv4 will output 100.64.0.33" )
statusCmd . MarkFlagsMutuallyExclusive ( "detail" , "json" , "yaml" , "ipv4" )
statusCmd . PersistentFlags ( ) . StringSliceVar ( & ipsFilter , "filter-by-ips" , [ ] string { } , "filters the detailed output by a list of one or more IPs, e.g., --filter-by-ips 100.64.0.100,100.64.0.200" )
2023-12-14 11:18:43 +01:00
statusCmd . PersistentFlags ( ) . StringSliceVar ( & prefixNamesFilter , "filter-by-names" , [ ] string { } , "filters the detailed output by a list of one or more peer FQDN or hostnames, e.g., --filter-by-names peer-a,peer-b.netbird.cloud" )
2023-02-23 20:13:19 +01:00
statusCmd . PersistentFlags ( ) . StringVar ( & statusFilter , "filter-by-status" , "" , "filters the detailed output by connection status(connected|disconnected), e.g., --filter-by-status connected" )
}
2022-05-22 18:53:47 +02:00
2023-02-23 20:13:19 +01:00
func statusFunc ( cmd * cobra . Command , args [ ] string ) error {
SetFlagsFromEnvVars ( rootCmd )
2022-07-05 19:47:50 +02:00
2023-02-23 20:13:19 +01:00
cmd . SetOut ( cmd . OutOrStdout ( ) )
2022-03-10 18:14:07 +01:00
2023-02-23 20:13:19 +01:00
err := parseFilters ( )
if err != nil {
return err
}
2022-03-08 14:47:55 +01:00
2023-02-23 20:13:19 +01:00
err = util . InitLog ( logLevel , "console" )
if err != nil {
return fmt . Errorf ( "failed initializing log %v" , err )
}
2022-03-08 14:47:55 +01:00
2024-04-26 17:20:10 +02:00
ctx := internal . CtxInitState ( cmd . Context ( ) )
2022-05-12 11:17:24 +02:00
2024-04-26 17:20:10 +02:00
resp , err := getStatus ( ctx )
2023-02-23 20:13:19 +01:00
if err != nil {
2023-09-04 17:03:44 +02:00
return err
2023-02-23 20:13:19 +01:00
}
2022-07-05 19:47:50 +02:00
2023-02-23 20:13:19 +01:00
if resp . GetStatus ( ) == string ( internal . StatusNeedsLogin ) || resp . GetStatus ( ) == string ( internal . StatusLoginFailed ) {
2023-02-24 19:01:54 +01:00
cmd . Printf ( "Daemon status: %s\n\n" +
2023-02-23 20:13:19 +01:00
"Run UP command to log in with SSO (interactive login):\n\n" +
" netbird up \n\n" +
"If you are running a self-hosted version and no SSO provider has been configured in your Management Server,\n" +
"you can use a setup-key:\n\n netbird up --management-url <YOUR_MANAGEMENT_URL> --setup-key <YOUR_SETUP_KEY>\n\n" +
2023-08-17 12:27:04 +02:00
"More info: https://docs.netbird.io/how-to/register-machines-using-setup-keys\n\n" ,
2023-02-24 19:01:54 +01:00
resp . GetStatus ( ) ,
2023-02-23 20:13:19 +01:00
)
2022-03-08 14:47:55 +01:00
return nil
2023-02-23 20:13:19 +01:00
}
2022-07-05 19:47:50 +02:00
2023-02-24 19:01:54 +01:00
if ipv4Flag {
cmd . Print ( parseInterfaceIP ( resp . GetFullStatus ( ) . GetLocalPeerState ( ) . GetIP ( ) ) )
return nil
}
2025-02-21 16:29:21 +01:00
var outputInformationHolder = nbstatus . ConvertToStatusOutputOverview ( resp , anonymizeFlag , statusFilter , prefixNamesFilter , prefixNamesFilterMap , ipsFilterMap )
2023-09-04 17:03:44 +02:00
var statusOutputString string
2023-02-27 17:06:20 +01:00
switch {
case detailFlag :
2025-02-21 16:29:21 +01:00
statusOutputString = nbstatus . ParseToFullDetailSummary ( outputInformationHolder )
2023-02-27 17:06:20 +01:00
case jsonFlag :
2025-02-21 16:29:21 +01:00
statusOutputString , err = nbstatus . ParseToJSON ( outputInformationHolder )
2023-02-27 17:06:20 +01:00
case yamlFlag :
2025-02-21 16:29:21 +01:00
statusOutputString , err = nbstatus . ParseToYAML ( outputInformationHolder )
2023-02-27 17:06:20 +01:00
default :
2025-02-21 16:29:21 +01:00
statusOutputString = nbstatus . ParseGeneralSummary ( outputInformationHolder , false , false , false )
2023-02-27 17:06:20 +01:00
}
if err != nil {
return err
2023-02-23 20:13:19 +01:00
}
cmd . Print ( statusOutputString )
return nil
2022-07-05 19:47:50 +02:00
}
2024-04-26 17:20:10 +02:00
func getStatus ( ctx context . Context ) ( * proto . StatusResponse , error ) {
2023-02-24 19:01:54 +01:00
conn , err := DialClientGRPCServer ( ctx , daemonAddr )
if err != nil {
return nil , fmt . Errorf ( "failed to connect to daemon error: %v\n" +
"If the daemon is not running please run: " +
"\nnetbird service install \nnetbird service start\n" , err )
}
defer conn . Close ( )
2024-04-26 17:20:10 +02:00
resp , err := proto . NewDaemonServiceClient ( conn ) . Status ( ctx , & proto . StatusRequest { GetFullPeerStatus : true } )
2023-02-24 19:01:54 +01:00
if err != nil {
return nil , fmt . Errorf ( "status failed: %v" , status . Convert ( err ) . Message ( ) )
}
return resp , nil
}
2022-07-05 19:47:50 +02:00
func parseFilters ( ) error {
switch strings . ToLower ( statusFilter ) {
case "" , "disconnected" , "connected" :
2023-12-14 11:18:43 +01:00
if strings . ToLower ( statusFilter ) != "" {
enableDetailFlagWhenFilterFlag ( )
}
2022-07-05 19:47:50 +02:00
default :
return fmt . Errorf ( "wrong status filter, should be one of connected|disconnected, got: %s" , statusFilter )
}
if len ( ipsFilter ) > 0 {
for _ , addr := range ipsFilter {
_ , err := netip . ParseAddr ( addr )
if err != nil {
return fmt . Errorf ( "got an invalid IP address in the filter: address %s, error %s" , addr , err )
}
ipsFilterMap [ addr ] = struct { } { }
2023-12-14 11:18:43 +01:00
enableDetailFlagWhenFilterFlag ( )
2022-07-05 19:47:50 +02:00
}
}
2023-12-14 11:18:43 +01:00
if len ( prefixNamesFilter ) > 0 {
for _ , name := range prefixNamesFilter {
prefixNamesFilterMap [ strings . ToLower ( name ) ] = struct { } { }
}
enableDetailFlagWhenFilterFlag ( )
}
2022-07-05 19:47:50 +02:00
return nil
}
2023-12-14 11:18:43 +01:00
func enableDetailFlagWhenFilterFlag ( ) {
if ! detailFlag && ! jsonFlag && ! yamlFlag {
detailFlag = true
}
}
2023-02-23 20:13:19 +01:00
func parseInterfaceIP ( interfaceIP string ) string {
2022-09-22 09:25:52 +02:00
ip , _ , err := net . ParseCIDR ( interfaceIP )
if err != nil {
return ""
}
2023-02-23 20:13:19 +01:00
return fmt . Sprintf ( "%s\n" , ip )
}