Skip to content

Commit ad8fcda

Browse files
authored
[client] Move some sys info to static place (#4446)
This PR refactors the system information collection code by moving static system information gathering to a dedicated location and separating platform-specific implementations. The primary goal is to improve code organization and maintainability by centralizing static info collection logic. Key changes: - Centralized static info collection into dedicated files with platform-specific implementations - Moved `StaticInfo` struct definition to the main static_info.go file - Added async initialization function `UpdateStaticInfoAsync()` across all platforms
1 parent d33f88d commit ad8fcda

13 files changed

+278
-198
lines changed

client/cmd/login.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ func doForegroundLogin(ctx context.Context, cmd *cobra.Command, setupKey string,
227227
}
228228

229229
// update host's static platform and system information
230-
system.UpdateStaticInfo()
230+
system.UpdateStaticInfoAsync()
231231

232232
configFilePath, err := activeProf.FilePath()
233233
if err != nil {

client/cmd/service_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func (p *program) Start(svc service.Service) error {
2727
log.Info("starting NetBird service") //nolint
2828

2929
// Collect static system and platform information
30-
system.UpdateStaticInfo()
30+
system.UpdateStaticInfoAsync()
3131

3232
// in any case, even if configuration does not exists we run daemon to serve CLI gRPC API.
3333
p.serv = grpc.NewServer()

client/system/info.go

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,6 @@ func (i *Info) SetFlags(
9595
i.LazyConnectionEnabled = lazyConnectionEnabled
9696
}
9797

98-
// StaticInfo is an object that contains machine information that does not change
99-
type StaticInfo struct {
100-
SystemSerialNumber string
101-
SystemProductName string
102-
SystemManufacturer string
103-
Environment Environment
104-
}
105-
10698
// extractUserAgent extracts Netbird's agent (client) name and version from the outgoing context
10799
func extractUserAgent(ctx context.Context) string {
108100
md, hasMeta := metadata.FromOutgoingContext(ctx)
@@ -195,10 +187,3 @@ func GetInfoWithChecks(ctx context.Context, checks []*proto.Checks) (*Info, erro
195187

196188
return info, nil
197189
}
198-
199-
// UpdateStaticInfo asynchronously updates static system and platform information
200-
func UpdateStaticInfo() {
201-
go func() {
202-
_ = updateStaticInfo()
203-
}()
204-
}

client/system/info_android.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ import (
1515
"github.com/netbirdio/netbird/version"
1616
)
1717

18+
// UpdateStaticInfoAsync is a no-op on Android as there is no static info to update
19+
func UpdateStaticInfoAsync() {
20+
// do nothing
21+
}
22+
1823
// GetInfo retrieves and parses the system information
1924
func GetInfo(ctx context.Context) *Info {
2025
kernel := "android"

client/system/info_darwin.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ import (
1919
"github.com/netbirdio/netbird/version"
2020
)
2121

22+
func UpdateStaticInfoAsync() {
23+
go updateStaticInfo()
24+
}
25+
2226
// GetInfo retrieves and parses the system information
2327
func GetInfo(ctx context.Context) *Info {
2428
utsname := unix.Utsname{}
@@ -41,7 +45,7 @@ func GetInfo(ctx context.Context) *Info {
4145
}
4246

4347
start := time.Now()
44-
si := updateStaticInfo()
48+
si := getStaticInfo()
4549
if time.Since(start) > 1*time.Second {
4650
log.Warnf("updateStaticInfo took %s", time.Since(start))
4751
}

client/system/info_freebsd.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ import (
1818
"github.com/netbirdio/netbird/version"
1919
)
2020

21+
// UpdateStaticInfoAsync is a no-op on Android as there is no static info to update
22+
func UpdateStaticInfoAsync() {
23+
// do nothing
24+
}
25+
2126
// GetInfo retrieves and parses the system information
2227
func GetInfo(ctx context.Context) *Info {
2328
out := _getInfo()

client/system/info_ios.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ import (
1010
"github.com/netbirdio/netbird/version"
1111
)
1212

13+
// UpdateStaticInfoAsync is a no-op on Android as there is no static info to update
14+
func UpdateStaticInfoAsync() {
15+
// do nothing
16+
}
17+
1318
// GetInfo retrieves and parses the system information
1419
func GetInfo(ctx context.Context) *Info {
1520

client/system/info_linux.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ var (
2323
getSystemInfo = defaultSysInfoImplementation
2424
)
2525

26+
func UpdateStaticInfoAsync() {
27+
go updateStaticInfo()
28+
}
29+
2630
// GetInfo retrieves and parses the system information
2731
func GetInfo(ctx context.Context) *Info {
2832
info := _getInfo()
@@ -48,7 +52,7 @@ func GetInfo(ctx context.Context) *Info {
4852
}
4953

5054
start := time.Now()
51-
si := updateStaticInfo()
55+
si := getStaticInfo()
5256
if time.Since(start) > 1*time.Second {
5357
log.Warnf("updateStaticInfo took %s", time.Since(start))
5458
}

client/system/info_windows.go

Lines changed: 13 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -2,187 +2,52 @@ package system
22

33
import (
44
"context"
5-
"fmt"
65
"os"
76
"runtime"
8-
"strings"
97
"time"
108

119
log "github.com/sirupsen/logrus"
12-
"github.com/yusufpapurcu/wmi"
13-
"golang.org/x/sys/windows/registry"
1410

1511
"github.com/netbirdio/netbird/version"
1612
)
1713

18-
type Win32_OperatingSystem struct {
19-
Caption string
20-
}
21-
22-
type Win32_ComputerSystem struct {
23-
Manufacturer string
24-
}
25-
26-
type Win32_ComputerSystemProduct struct {
27-
Name string
28-
}
29-
30-
type Win32_BIOS struct {
31-
SerialNumber string
14+
func UpdateStaticInfoAsync() {
15+
go updateStaticInfo()
3216
}
3317

3418
// GetInfo retrieves and parses the system information
3519
func GetInfo(ctx context.Context) *Info {
36-
osName, osVersion := getOSNameAndVersion()
37-
buildVersion := getBuildVersion()
38-
39-
addrs, err := networkAddresses()
40-
if err != nil {
41-
log.Warnf("failed to discover network addresses: %s", err)
42-
}
43-
4420
start := time.Now()
45-
si := updateStaticInfo()
21+
si := getStaticInfo()
4622
if time.Since(start) > 1*time.Second {
4723
log.Warnf("updateStaticInfo took %s", time.Since(start))
4824
}
4925

5026
gio := &Info{
5127
Kernel: "windows",
52-
OSVersion: osVersion,
28+
OSVersion: si.OSVersion,
5329
Platform: "unknown",
54-
OS: osName,
30+
OS: si.OSName,
5531
GoOS: runtime.GOOS,
5632
CPUs: runtime.NumCPU(),
57-
KernelVersion: buildVersion,
58-
NetworkAddresses: addrs,
33+
KernelVersion: si.BuildVersion,
5934
SystemSerialNumber: si.SystemSerialNumber,
6035
SystemProductName: si.SystemProductName,
6136
SystemManufacturer: si.SystemManufacturer,
6237
Environment: si.Environment,
6338
}
6439

40+
addrs, err := networkAddresses()
41+
if err != nil {
42+
log.Warnf("failed to discover network addresses: %s", err)
43+
} else {
44+
gio.NetworkAddresses = addrs
45+
}
46+
6547
systemHostname, _ := os.Hostname()
6648
gio.Hostname = extractDeviceName(ctx, systemHostname)
6749
gio.NetbirdVersion = version.NetbirdVersion()
6850
gio.UIVersion = extractUserAgent(ctx)
6951

7052
return gio
7153
}
72-
73-
func sysInfo() (serialNumber string, productName string, manufacturer string) {
74-
var err error
75-
serialNumber, err = sysNumber()
76-
if err != nil {
77-
log.Warnf("failed to get system serial number: %s", err)
78-
}
79-
80-
productName, err = sysProductName()
81-
if err != nil {
82-
log.Warnf("failed to get system product name: %s", err)
83-
}
84-
85-
manufacturer, err = sysManufacturer()
86-
if err != nil {
87-
log.Warnf("failed to get system manufacturer: %s", err)
88-
}
89-
90-
return serialNumber, productName, manufacturer
91-
}
92-
93-
func getOSNameAndVersion() (string, string) {
94-
var dst []Win32_OperatingSystem
95-
query := wmi.CreateQuery(&dst, "")
96-
err := wmi.Query(query, &dst)
97-
if err != nil {
98-
log.Error(err)
99-
return "Windows", getBuildVersion()
100-
}
101-
102-
if len(dst) == 0 {
103-
return "Windows", getBuildVersion()
104-
}
105-
106-
split := strings.Split(dst[0].Caption, " ")
107-
108-
if len(split) <= 3 {
109-
return "Windows", getBuildVersion()
110-
}
111-
112-
name := split[1]
113-
version := split[2]
114-
if split[2] == "Server" {
115-
name = fmt.Sprintf("%s %s", split[1], split[2])
116-
version = split[3]
117-
}
118-
119-
return name, version
120-
}
121-
122-
func getBuildVersion() string {
123-
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
124-
if err != nil {
125-
log.Error(err)
126-
return "0.0.0.0"
127-
}
128-
defer func() {
129-
deferErr := k.Close()
130-
if deferErr != nil {
131-
log.Error(deferErr)
132-
}
133-
}()
134-
135-
major, _, err := k.GetIntegerValue("CurrentMajorVersionNumber")
136-
if err != nil {
137-
log.Error(err)
138-
}
139-
minor, _, err := k.GetIntegerValue("CurrentMinorVersionNumber")
140-
if err != nil {
141-
log.Error(err)
142-
}
143-
build, _, err := k.GetStringValue("CurrentBuildNumber")
144-
if err != nil {
145-
log.Error(err)
146-
}
147-
// Update Build Revision
148-
ubr, _, err := k.GetIntegerValue("UBR")
149-
if err != nil {
150-
log.Error(err)
151-
}
152-
ver := fmt.Sprintf("%d.%d.%s.%d", major, minor, build, ubr)
153-
return ver
154-
}
155-
156-
func sysNumber() (string, error) {
157-
var dst []Win32_BIOS
158-
query := wmi.CreateQuery(&dst, "")
159-
err := wmi.Query(query, &dst)
160-
if err != nil {
161-
return "", err
162-
}
163-
return dst[0].SerialNumber, nil
164-
}
165-
166-
func sysProductName() (string, error) {
167-
var dst []Win32_ComputerSystemProduct
168-
query := wmi.CreateQuery(&dst, "")
169-
err := wmi.Query(query, &dst)
170-
if err != nil {
171-
return "", err
172-
}
173-
// `ComputerSystemProduct` could be empty on some virtualized systems
174-
if len(dst) < 1 {
175-
return "unknown", nil
176-
}
177-
return dst[0].Name, nil
178-
}
179-
180-
func sysManufacturer() (string, error) {
181-
var dst []Win32_ComputerSystem
182-
query := wmi.CreateQuery(&dst, "")
183-
err := wmi.Query(query, &dst)
184-
if err != nil {
185-
return "", err
186-
}
187-
return dst[0].Manufacturer, nil
188-
}

client/system/static_info.go

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,34 @@
33
package system
44

55
import (
6-
"context"
76
"sync"
8-
"time"
9-
10-
"github.com/netbirdio/netbird/client/system/detect_cloud"
11-
"github.com/netbirdio/netbird/client/system/detect_platform"
127
)
138

149
var (
1510
staticInfo StaticInfo
1611
once sync.Once
1712
)
1813

19-
func updateStaticInfo() StaticInfo {
14+
// StaticInfo is an object that contains machine information that does not change
15+
type StaticInfo struct {
16+
SystemSerialNumber string
17+
SystemProductName string
18+
SystemManufacturer string
19+
Environment Environment
20+
21+
// Windows specific fields
22+
OSName string
23+
OSVersion string
24+
BuildVersion string
25+
}
26+
27+
func updateStaticInfo() {
2028
once.Do(func() {
21-
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
22-
defer cancel()
23-
wg := sync.WaitGroup{}
24-
wg.Add(3)
25-
go func() {
26-
staticInfo.SystemSerialNumber, staticInfo.SystemProductName, staticInfo.SystemManufacturer = sysInfo()
27-
wg.Done()
28-
}()
29-
go func() {
30-
staticInfo.Environment.Cloud = detect_cloud.Detect(ctx)
31-
wg.Done()
32-
}()
33-
go func() {
34-
staticInfo.Environment.Platform = detect_platform.Detect(ctx)
35-
wg.Done()
36-
}()
37-
wg.Wait()
29+
staticInfo = newStaticInfo()
3830
})
31+
}
32+
33+
func getStaticInfo() StaticInfo {
34+
updateStaticInfo()
3935
return staticInfo
4036
}

0 commit comments

Comments
 (0)