Skip to content

Commit 5236277

Browse files
committed
Add manual and IPinfo node location detection
1 parent 843dd0e commit 5236277

11 files changed

Lines changed: 891 additions & 169 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ Formatting rules:
1515

1616
## [Unreleased]
1717

18+
## [2026.5.3] - 2026-05-14
19+
20+
### Added
21+
22+
- Added manual node location overrides and optional IPinfo public-IP geolocation fallback for non-cloud hosts, with public-IP lookup disabled unless explicitly configured.
23+
1824
## [2026.5.2] - 2026-05-14
1925

2026
### Fixed

internal/agent/enrollment.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import (
1111
"time"
1212

1313
"github.com/noderax/noderax-agent/internal/api"
14-
"github.com/noderax/noderax-agent/internal/cloudmetadata"
1514
"github.com/noderax/noderax-agent/internal/config"
15+
"github.com/noderax/noderax-agent/internal/nodelocation"
1616
"github.com/noderax/noderax-agent/internal/system"
1717
)
1818

@@ -74,7 +74,7 @@ func RunInteractiveEnrollment(
7474
if strings.TrimSpace(operatingSystem) == "" {
7575
operatingSystem = hostInfo.OS
7676
}
77-
location := detectCloudLocation(ctx, logger)
77+
location := detectNodeLocation(ctx, cfg, logger)
7878

7979
requestCtx, cancel := context.WithTimeout(ctx, cfg.RequestTimeout)
8080
defer cancel()
@@ -153,7 +153,7 @@ func RunBootstrapEnrollment(
153153
if strings.TrimSpace(operatingSystem) == "" {
154154
operatingSystem = hostInfo.OS
155155
}
156-
location := detectCloudLocation(ctx, logger)
156+
location := detectNodeLocation(ctx, cfg, logger)
157157

158158
requestCtx, cancel := context.WithTimeout(ctx, cfg.RequestTimeout)
159159
defer cancel()
@@ -330,18 +330,19 @@ func persistIdentity(
330330
return nil
331331
}
332332

333-
var detectCloudLocation = func(ctx context.Context, logger *slog.Logger) *api.NodeLocation {
334-
location, err := cloudmetadata.Detect(ctx)
333+
var detectNodeLocation = func(ctx context.Context, cfg config.Config, logger *slog.Logger) *api.NodeLocation {
334+
location, err := nodelocation.Detect(ctx, cfg)
335335
if err != nil {
336336
if logger != nil {
337-
logger.Debug("cloud metadata location detection skipped", "error", err)
337+
logger.Debug("node location detection skipped", "error", err)
338338
}
339339
return nil
340340
}
341341
if location != nil && logger != nil {
342342
logger.Info(
343-
"cloud metadata location detected",
343+
"node location detected",
344344
"provider", location.Provider,
345+
"source", location.Source,
345346
"region", location.Region,
346347
"zone", location.Zone,
347348
)

internal/agent/enrollment_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ import (
1818

1919
func TestRunInteractiveEnrollmentUsesExpectedInitiatePayload(t *testing.T) {
2020
tmpDir := t.TempDir()
21-
originalDetectCloudLocation := detectCloudLocation
22-
detectCloudLocation = func(context.Context, *slog.Logger) *api.NodeLocation {
21+
originalDetectNodeLocation := detectNodeLocation
22+
detectNodeLocation = func(context.Context, config.Config, *slog.Logger) *api.NodeLocation {
2323
return &api.NodeLocation{
2424
Provider: "aws",
2525
Source: "cloud_metadata",
@@ -28,7 +28,7 @@ func TestRunInteractiveEnrollmentUsesExpectedInitiatePayload(t *testing.T) {
2828
}
2929
}
3030
t.Cleanup(func() {
31-
detectCloudLocation = originalDetectCloudLocation
31+
detectNodeLocation = originalDetectNodeLocation
3232
})
3333

3434
cfg := config.Config{
@@ -84,7 +84,7 @@ func TestRunInteractiveEnrollmentUsesExpectedInitiatePayload(t *testing.T) {
8484
t.Fatalf("agent version mismatch: got %q want %q", client.initiateRequest.AdditionalInfo.AgentVersion, "dev")
8585
}
8686
if client.initiateRequest.AdditionalInfo.Location == nil {
87-
t.Fatal("expected cloud metadata location to be included")
87+
t.Fatal("expected node location to be included")
8888
}
8989
if client.initiateRequest.AdditionalInfo.Location.Region != "eu-central-1" {
9090
t.Fatalf("location region mismatch: got %q want %q", client.initiateRequest.AdditionalInfo.Location.Region, "eu-central-1")

internal/agent/service.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import (
1010
"time"
1111

1212
"github.com/noderax/noderax-agent/internal/api"
13-
"github.com/noderax/noderax-agent/internal/cloudmetadata"
1413
"github.com/noderax/noderax-agent/internal/config"
1514
"github.com/noderax/noderax-agent/internal/metrics"
15+
"github.com/noderax/noderax-agent/internal/nodelocation"
1616
"github.com/noderax/noderax-agent/internal/realtime"
1717
"github.com/noderax/noderax-agent/internal/rootaccess"
1818
"github.com/noderax/noderax-agent/internal/system"
@@ -159,7 +159,7 @@ func NewService(cfg config.Config, client *api.Client, logger *slog.Logger, vers
159159
}
160160
if realtimeService != nil {
161161
realtimeService.SetRuntimeAgentVersion(version)
162-
setRealtimeCloudLocation(context.Background(), logger, realtimeService, false)
162+
setRealtimeNodeLocation(context.Background(), cfg, logger, realtimeService, false)
163163
hostInfo, hostInfoErr := system.HostInfo(context.Background())
164164
if hostInfoErr != nil {
165165
logger.Warn("failed to read host metadata for realtime auth", "error", hostInfoErr)
@@ -210,7 +210,7 @@ func (s *Service) Run(ctx context.Context) error {
210210
name string
211211
run func(context.Context) error
212212
}{
213-
{name: "cloud-metadata", run: s.runCloudMetadataSync},
213+
{name: "node-location", run: s.runNodeLocationSync},
214214
{name: "realtime", run: s.realtime.Run},
215215
{name: "metrics", run: s.metrics.Run},
216216
{name: "tasks", run: s.tasks.Run},
@@ -246,7 +246,7 @@ func (s *Service) Run(ctx context.Context) error {
246246
}
247247
}
248248

249-
func (s *Service) runCloudMetadataSync(ctx context.Context) error {
249+
func (s *Service) runNodeLocationSync(ctx context.Context) error {
250250
if s.realtime == nil || s.realtime.RuntimeLocation() != nil {
251251
return nil
252252
}
@@ -267,24 +267,25 @@ func (s *Service) runCloudMetadataSync(ctx context.Context) error {
267267
case <-timer.C:
268268
}
269269

270-
if setRealtimeCloudLocation(ctx, s.logger, s.realtime, true) {
270+
if setRealtimeNodeLocation(ctx, s.cfg, s.logger, s.realtime, true) {
271271
return nil
272272
}
273273
}
274274

275275
return nil
276276
}
277277

278-
func setRealtimeCloudLocation(
278+
func setRealtimeNodeLocation(
279279
ctx context.Context,
280+
cfg config.Config,
280281
logger *slog.Logger,
281282
realtimeService *realtime.Service,
282283
refreshAuth bool,
283284
) bool {
284-
location, err := cloudmetadata.Detect(ctx)
285+
location, err := nodelocation.Detect(ctx, cfg)
285286
if err != nil {
286287
if logger != nil {
287-
logger.Debug("cloud metadata location detection skipped", "error", err)
288+
logger.Debug("node location detection skipped", "error", err)
288289
}
289290
return false
290291
}
@@ -295,8 +296,9 @@ func setRealtimeCloudLocation(
295296
realtimeService.SetRuntimeLocation(location)
296297
if logger != nil {
297298
logger.Info(
298-
"cloud metadata location detected",
299+
"node location detected",
299300
"provider", location.Provider,
301+
"source", location.Source,
300302
"region", location.Region,
301303
"zone", location.Zone,
302304
)
@@ -305,7 +307,7 @@ func setRealtimeCloudLocation(
305307
refreshCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
306308
defer cancel()
307309
if err := realtimeService.RefreshAuth(refreshCtx); err != nil && !errors.Is(err, realtime.ErrSessionNotActive) && logger != nil {
308-
logger.Debug("cloud metadata realtime auth refresh skipped", "error", err)
310+
logger.Debug("node location realtime auth refresh skipped", "error", err)
309311
}
310312
}
311313
return true

0 commit comments

Comments
 (0)