Skip to content

Commit 69c44af

Browse files
committed
refact: simplify bootstrap logic
1 parent f54402c commit 69c44af

14 files changed

Lines changed: 422 additions & 587 deletions

File tree

cmd/demo-app/main.go

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ func main() {
3434
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339})
3535
logger := log.With().Str("component", "demo-app").Logger()
3636

37-
flag.StringVar(&flagRelayURLs, "relays", "https://localhost:4017", "additional relay API URLs (comma-separated; scheme omitted defaults to https; appended to registry.json defaults unless --default-relays=false is set) [env: RELAYS]")
38-
flag.BoolVar(&flagDefaultRelays, "default-relays", utils.ParseBoolEnv("DEFAULT_RELAYS", true), "include repository registry.json default relays [env: DEFAULT_RELAYS]")
37+
flag.StringVar(&flagRelayURLs, "relays", "https://localhost:4017", "additional relay API URLs (comma-separated; scheme omitted defaults to https; merged with public registry relays unless --default-relays=false is set) [env: RELAYS]")
38+
flag.BoolVar(&flagDefaultRelays, "default-relays", utils.ParseBoolEnv("DEFAULT_RELAYS", true), "include public registry relays [env: DEFAULT_RELAYS]")
3939
flag.StringVar(&flagAddr, "addr", "127.0.0.1:8092", "local demo HTTP listen address (host:port or URL; disable if empty)")
4040
flag.StringVar(&flagName, "name", "demo-app", "public hostname prefix (single DNS label)")
4141
flag.StringVar(&flagDesc, "description", "Portal demo connectivity app", "lease description")
@@ -58,20 +58,17 @@ func runDemo() error {
5858
defer stop()
5959

6060
relayURLs := utils.SplitCSV(flagRelayURLs)
61-
if flagDefaultRelays {
62-
relayURLs = sdk.WithDefaultRelayURLs(ctx, "", relayURLs...)
63-
}
64-
relayURLs, err := utils.NormalizeRelayURLs(relayURLs)
65-
if err != nil {
66-
return fmt.Errorf("resolve relay urls: %w", err)
67-
}
68-
69-
exposure, err := sdk.Expose(ctx, relayURLs, flagName, false, types.LeaseMetadata{
70-
Description: flagDesc,
71-
Tags: utils.SplitCSV(flagTags),
72-
Owner: flagOwner,
73-
Thumbnail: flagThumbnail,
74-
Hide: flagHide,
61+
exposure, err := sdk.Expose(ctx, sdk.ExposeConfig{
62+
RelayURLs: relayURLs,
63+
DefaultRelayEnabled: flagDefaultRelays,
64+
Name: flagName,
65+
Metadata: types.LeaseMetadata{
66+
Description: flagDesc,
67+
Tags: utils.SplitCSV(flagTags),
68+
Owner: flagOwner,
69+
Thumbnail: flagThumbnail,
70+
Hide: flagHide,
71+
},
7572
})
7673
if err != nil {
7774
return fmt.Errorf("exposure listen error: %w", err)

cmd/demo-udp/main.go

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ func main() {
3636
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339})
3737
logger := log.With().Str("component", "demo-udp").Logger()
3838

39-
flag.StringVar(&flagRelayURLs, "relays", "https://localhost:4017", "additional relay API URLs (comma-separated; scheme omitted defaults to https; appended to registry.json defaults unless --default-relays=false is set) [env: RELAYS]")
40-
flag.BoolVar(&flagDefaultRelays, "default-relays", utils.ParseBoolEnv("DEFAULT_RELAYS", false), "include repository registry.json default relays [env: DEFAULT_RELAYS]")
39+
flag.StringVar(&flagRelayURLs, "relays", "https://localhost:4017", "additional relay API URLs (comma-separated; scheme omitted defaults to https; merged with public registry relays unless --default-relays=false is set) [env: RELAYS]")
40+
flag.BoolVar(&flagDefaultRelays, "default-relays", utils.ParseBoolEnv("DEFAULT_RELAYS", false), "include public registry relays [env: DEFAULT_RELAYS]")
4141
flag.StringVar(&flagName, "name", "demo-udp", "public hostname prefix (single DNS label)")
4242
flag.StringVar(&flagDesc, "description", "Portal demo UDP echo service", "lease description")
4343
flag.StringVar(&flagTags, "tags", "demo,udp,echo", "comma-separated lease tags")
@@ -59,20 +59,18 @@ func runDemoUDP() error {
5959
defer stop()
6060

6161
relayURLs := utils.SplitCSV(flagRelayURLs)
62-
if flagDefaultRelays {
63-
relayURLs = sdk.WithDefaultRelayURLs(ctx, "", relayURLs...)
64-
}
65-
relayURLs, err := utils.NormalizeRelayURLs(relayURLs)
66-
if err != nil {
67-
return fmt.Errorf("resolve relay urls: %w", err)
68-
}
69-
70-
exposure, err := sdk.Expose(ctx, relayURLs, flagName, true, types.LeaseMetadata{
71-
Description: flagDesc,
72-
Tags: utils.SplitCSV(flagTags),
73-
Owner: flagOwner,
74-
Thumbnail: flagThumbnail,
75-
Hide: flagHide,
62+
exposure, err := sdk.Expose(ctx, sdk.ExposeConfig{
63+
RelayURLs: relayURLs,
64+
DefaultRelayEnabled: flagDefaultRelays,
65+
Name: flagName,
66+
UDPEnabled: true,
67+
Metadata: types.LeaseMetadata{
68+
Description: flagDesc,
69+
Tags: utils.SplitCSV(flagTags),
70+
Owner: flagOwner,
71+
Thumbnail: flagThumbnail,
72+
Hide: flagHide,
73+
},
7674
})
7775
if err != nil {
7876
return fmt.Errorf("exposure listen error: %w", err)

cmd/portal-tunnel/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Flags:
4242

4343
```text
4444
--relays Portal relay API URLs (comma-separated, https only)
45-
--default-relays Include repository registry.json public relays
45+
--default-relays Include public registry relays
4646
--name Public hostname prefix (single DNS label); auto-generated when omitted
4747
--description Service description metadata
4848
--tags Service tags metadata (comma-separated)
@@ -78,7 +78,7 @@ Legacy execution compatibility has been removed:
7878
- The tunnel consumes one aggregate SDK listener, so the CLI no longer manages per-relay listener loops itself.
7979
- Relay startup and reconnect failures are retried independently in the background. A relay that is down does not stop healthy relays from continuing to serve traffic.
8080
- The tunnel starts once relay URLs pass local validation. Remote compatibility checks, lease registration, and reconnects continue in the background until each relay becomes ready.
81-
- The configured relay list is either `registry.json + installed/configured relay URLs` or, with `--default-relays=false`, just the explicit relay URLs. Published public URLs appear only for relays that have registered successfully.
81+
- The configured relay list is either `public registry + installed/configured relay URLs` or, with `--default-relays=false`, just the explicit relay URLs. Published public URLs appear only for relays that have registered successfully.
8282
- SDK callers that do not set `ListenerConfig.RetryCount` use infinite retry semantics for each relay.
8383
- Tenant TLS is provisioned automatically through the relay keyless signer. The SDK fetches the relay certificate chain and uses `/v1/sign` for remote signing.
8484
- When the local service is unreachable, the tunnel returns an HTTP 503 page.

cmd/portal-tunnel/main.go

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,6 @@ func runExposeCommand(args []string) error {
168168
relayInputs = []string{explicitRelays}
169169
}
170170

171-
relayURLs, err := resolveRelayURLs(ctx, "", relayInputs, defaultRelays)
172-
if err != nil {
173-
return fmt.Errorf("resolve relay urls: %w", err)
174-
}
175-
if len(relayURLs) == 0 {
176-
return errors.New("no relay URLs configured; run the installer first or pass --relays")
177-
}
178-
179171
previousOwnerPrivateKey := cfg.OwnerPrivateKey
180172
if strings.TrimSpace(privateKey) != "" {
181173
cfg.OwnerPrivateKey = privateKey
@@ -185,11 +177,12 @@ func runExposeCommand(args []string) error {
185177
ownerPrivateKey = &cfg.OwnerPrivateKey
186178
}
187179

188-
exposure, err := sdk.ExposeWithConfig(ctx, sdk.ExposeConfig{
189-
RelayURLs: relayURLs,
190-
Name: name,
191-
UDPEnabled: udp,
192-
Discovery: discoveryEnabled,
180+
exposure, err := sdk.Expose(ctx, sdk.ExposeConfig{
181+
RelayURLs: relayInputs,
182+
DefaultRelayEnabled: defaultRelays,
183+
Name: name,
184+
UDPEnabled: udp,
185+
Discovery: discoveryEnabled,
193186
Metadata: types.LeaseMetadata{
194187
Description: desc,
195188
Tags: utils.SplitCSV(tags),
@@ -261,7 +254,7 @@ func runListCommand(args []string) error {
261254
relayInputs = []string{explicitRelays}
262255
}
263256

264-
relayURLs, err := resolveRelayURLs(ctx, "", relayInputs, defaultRelays)
257+
relayURLs, err := sdk.ResolveRelayURLs(ctx, relayInputs, defaultRelays)
265258
if err != nil {
266259
return fmt.Errorf("resolve relay urls: %w", err)
267260
}
@@ -366,17 +359,6 @@ func runTunnel(
366359
return errors.Join(waitErr, udpErr, closeErr)
367360
}
368361

369-
func resolveRelayURLs(ctx context.Context, registryURL string, inputs []string, includeDefaultRelays bool) ([]string, error) {
370-
if includeDefaultRelays {
371-
relayURLs := sdk.WithDefaultRelayURLs(ctx, registryURL, inputs...)
372-
if len(relayURLs) == 0 {
373-
return nil, nil
374-
}
375-
return relayURLs, nil
376-
}
377-
return utils.NormalizeRelayURLs(inputs)
378-
}
379-
380362
var exposeNameOpeners = []string{
381363
"arcade", "bouncy", "bravo", "bubble", "candy", "cosmic", "dapper", "electric",
382364
"fancy", "fizzy", "flashy", "fuzzy", "gentle", "glitter", "golden", "happy",

docs/architecture.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,13 @@ That distinction matters because `/sdk/connect` stops being ordinary HTTP once h
115115

116116
### SDK (`sdk/`)
117117

118-
- `WithDefaultRelayURLs`: fetches the default Portal relay list from the repository-root `registry.json`, appends explicit relay inputs, and normalizes the combined list
118+
- `ExposeConfig.DefaultRelayEnabled`: when true, `Expose` fetches the default Portal relay registry, merges it with explicit relay inputs, and normalizes the result
119119
- Entry points can opt out of registry defaults and call `utils.NormalizeRelayURLs` directly when they need explicit relay inputs only
120120
- `Listener`: validates one relay URL locally, then starts relay compatibility checks, lease registration, reverse session maintenance, and lease renewal in the background until ready
121121
- `api_client.go`: internal relay client for control-plane requests, reverse session dialing, and internal QUIC tunnel setup
122122
- `ListenerConfig.RetryCount <= 0` means retry forever; positive values close the listener after the retry budget is exhausted
123-
- Default app flow is `WithDefaultRelayURLs -> NewListener -> PublicURL -> http.Server.Serve(listener)` or `WithDefaultRelayURLs -> Expose -> PublicURLs -> http.Server.Serve(exposure)`, with an opt-out path for explicit relay inputs only
123+
- `NewListener` callers provide explicit normalized relay URLs
124+
- Default exposure flow is `Expose{DefaultRelayEnabled: true} -> PublicURLs -> http.Server.Serve(exposure)`, with an opt-out path for explicit relay inputs only
124125
- `expose.go`: optional `RunHTTP` helper for serving one handler on both a local HTTP port and the relay listener
125126
- `Expose` keeps one listener per configured relay URL. Relay startup and reconnect failures are retried independently per relay, and successful relays remain available while failed relays keep retrying in the background
126127
- `Exposure.RelayURLs()` returns the configured normalized relay URLs, while `Exposure.PublicURLs()` returns only relays that are currently registered and ready

portal/api_server.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func (s *Server) apiHandler(base *http.ServeMux, keylessSignerHandler http.Handl
8080
base.ServeHTTP(w, r)
8181
return
8282
}
83-
s.discovery.ServeHTTP(w, r)
83+
discovery.ServeHTTP(w, r, []string{s.cfg.PortalURL}, s.discoveryBootstrapsSnapshot(), s.discover)
8484
case types.PathV1Sign:
8585
if keylessSignerHandler == nil {
8686
http.NotFound(w, r)
@@ -517,17 +517,17 @@ func (s *Server) registerLease(req types.RegisterRequest, clientIP string) (type
517517
record.Close()
518518
return types.RegisterResponse{}, err
519519
}
520-
if s.discovery != nil {
521-
if err := s.discovery.MergeBootstraps(bootstraps); err != nil {
520+
if s.DiscoveryEnabled() {
521+
if err := s.mergeDiscoveryBootstraps(bootstraps); err != nil {
522522
record.Close()
523523
_, _ = s.registry.Unregister(record.ID, record.ReverseToken)
524524
return types.RegisterResponse{}, err
525525
}
526526
}
527527

528528
responseBootstraps := append([]string(nil), s.cfg.Bootstraps...)
529-
if s.discovery != nil {
530-
responseBootstraps = s.discovery.Bootstraps()
529+
if s.DiscoveryEnabled() {
530+
responseBootstraps = s.discoveryBootstrapsSnapshot()
531531
} else {
532532
responseBootstraps, err = utils.NormalizeRelayURLs(append(responseBootstraps, record.Bootstraps...))
533533
if err != nil {

0 commit comments

Comments
 (0)