Skip to content

Commit f2edff8

Browse files
committed
feat: add getBuilderInfo helper
1 parent c29a388 commit f2edff8

File tree

1 file changed

+74
-34
lines changed

1 file changed

+74
-34
lines changed

internal/build/imgsrc/docker.go

Lines changed: 74 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ import (
2626
"github.com/pkg/errors"
2727
"github.com/spf13/viper"
2828
fly "github.com/superfly/fly-go"
29+
"go.opentelemetry.io/otel/attribute"
30+
"go.opentelemetry.io/otel/trace"
31+
2932
"github.com/superfly/flyctl/agent"
3033
"github.com/superfly/flyctl/flyctl"
3134
"github.com/superfly/flyctl/helpers"
@@ -37,8 +40,6 @@ import (
3740
"github.com/superfly/flyctl/internal/tracing"
3841
"github.com/superfly/flyctl/iostreams"
3942
"github.com/superfly/flyctl/terminal"
40-
"go.opentelemetry.io/otel/attribute"
41-
"go.opentelemetry.io/otel/trace"
4243
)
4344

4445
var (
@@ -47,30 +48,39 @@ var (
4748
)
4849

4950
type dockerClientFactory struct {
50-
mode DockerDaemonType
51-
remote bool
52-
buildFn func(ctx context.Context, build *build) (*dockerclient.Client, error)
53-
apiClient flyutil.Client
54-
appName string
51+
mode DockerDaemonType
52+
remote bool
53+
buildFn func(ctx context.Context, build *build) (*dockerclient.Client, error)
54+
apiClient flyutil.Client
55+
appName string
56+
builderRegion string // Store the region for remote builders
5557
}
5658

5759
func newDockerClientFactory(daemonType DockerDaemonType, apiClient flyutil.Client, appName string, streams *iostreams.IOStreams, connectOverWireguard, recreateBuilder bool) *dockerClientFactory {
5860
useManagedBuilder := daemonType.UseManagedBuilder()
5961
remoteFactory := func() *dockerClientFactory {
6062
terminal.Debug("trying remote docker daemon")
61-
return &dockerClientFactory{
62-
mode: daemonType,
63-
remote: true,
64-
buildFn: func(ctx context.Context, build *build) (*dockerclient.Client, error) {
65-
cfg := config.FromContext(ctx)
66-
if cfg.DisableManagedBuilders {
67-
useManagedBuilder = false
68-
}
69-
return newRemoteDockerClient(ctx, apiClient, appName, streams, build, cachedDocker, connectOverWireguard, useManagedBuilder, recreateBuilder)
70-
},
63+
factory := &dockerClientFactory{
64+
mode: daemonType,
65+
remote: true,
7166
apiClient: apiClient,
7267
appName: appName,
7368
}
69+
70+
factory.buildFn = func(ctx context.Context, build *build) (*dockerclient.Client, error) {
71+
cfg := config.FromContext(ctx)
72+
if cfg.DisableManagedBuilders {
73+
useManagedBuilder = false
74+
}
75+
client, region, err := newRemoteDockerClient(ctx, apiClient, appName, streams, build, cachedDocker, connectOverWireguard, useManagedBuilder, recreateBuilder)
76+
if err == nil {
77+
// Store the region in the factory for later use
78+
factory.builderRegion = region
79+
}
80+
return client, err
81+
}
82+
83+
return factory
7484
}
7585

7686
localFactory := func() *dockerClientFactory {
@@ -236,14 +246,14 @@ func logClearLinesAbove(streams *iostreams.IOStreams, count int) {
236246
}
237247
}
238248

239-
func newRemoteDockerClient(ctx context.Context, apiClient flyutil.Client, appName string, streams *iostreams.IOStreams, build *build, cachedClient *dockerclient.Client, connectOverWireguard, useManagedBuilder bool, recreateBuilder bool) (c *dockerclient.Client, err error) {
249+
func newRemoteDockerClient(ctx context.Context, apiClient flyutil.Client, appName string, streams *iostreams.IOStreams, build *build, cachedClient *dockerclient.Client, connectOverWireguard, useManagedBuilder bool, recreateBuilder bool) (c *dockerclient.Client, region string, err error) {
240250
ctx, span := tracing.GetTracer().Start(ctx, "build_remote_docker_client", trace.WithAttributes(
241251
attribute.Bool("connect_over_wireguard", connectOverWireguard),
242252
))
243253
defer span.End()
244254
if cachedClient != nil {
245255
span.AddEvent("using cached docker client")
246-
return cachedClient, nil
256+
return cachedClient, "", nil
247257
}
248258

249259
startedAt := time.Now()
@@ -264,7 +274,7 @@ func newRemoteDockerClient(ctx context.Context, apiClient flyutil.Client, appNam
264274
}
265275
if err != nil {
266276
tracing.RecordError(span, err, "failed to init remote builder machine")
267-
return nil, err
277+
return nil, "", err
268278
}
269279

270280
if useManagedBuilder {
@@ -286,7 +296,7 @@ func newRemoteDockerClient(ctx context.Context, apiClient flyutil.Client, appNam
286296
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
287297
if err != nil {
288298
tracing.RecordError(span, err, "failed to create remote builder request")
289-
return nil, err
299+
return nil, "", err
290300
}
291301

292302
req.SetBasicAuth(appName, config.Tokens(ctx).Docker())
@@ -297,7 +307,7 @@ func newRemoteDockerClient(ctx context.Context, apiClient flyutil.Client, appNam
297307
res, err := client.Do(req)
298308
if err != nil {
299309
tracing.RecordError(span, err, "failed to get remote builder settings")
300-
return nil, err
310+
return nil, "", err
301311
}
302312

303313
if res.StatusCode == http.StatusNotFound {
@@ -308,14 +318,14 @@ func newRemoteDockerClient(ctx context.Context, apiClient flyutil.Client, appNam
308318
err := apiClient.DeleteApp(ctx, app.Name)
309319
if err != nil {
310320
tracing.RecordError(span, err, "failed to destroy old incompatible remote builder")
311-
return nil, err
321+
return nil, "", err
312322
}
313323

314324
fmt.Fprintln(streams.Out, streams.ColorScheme().Yellow("🔧 creating fresh remote builder, (this might take a while ...)"))
315325
machine, app, err = remoteBuilderMachine(ctx, apiClient, appName, false)
316326
if err != nil {
317327
tracing.RecordError(span, err, "failed to init remote builder machine")
318-
return nil, err
328+
return nil, "", err
319329
}
320330
logClearLinesAbove(streams, 1)
321331
fmt.Fprintln(streams.Out, streams.ColorScheme().Green("✓ compatible remote builder created"))
@@ -329,6 +339,7 @@ func newRemoteDockerClient(ctx context.Context, apiClient flyutil.Client, appNam
329339

330340
remoteBuilderAppName := app.Name
331341
remoteBuilderOrg := app.Organization.Slug
342+
builderRegion := machine.Region
332343

333344
build.SetBuilderMetaPart1(remoteBuilderType, remoteBuilderAppName, machine.ID)
334345

@@ -384,7 +395,7 @@ func newRemoteDockerClient(ctx context.Context, apiClient flyutil.Client, appNam
384395
if host == "" {
385396
err = errors.New("machine did not have a private IP")
386397
tracing.RecordError(span, err, "failed to boot remote builder")
387-
return nil, err
398+
return nil, "", err
388399
}
389400

390401
builderHostOverride, ok := os.LookupEnv("FLY_RCHAB_OVERRIDE_HOST")
@@ -409,10 +420,10 @@ func newRemoteDockerClient(ctx context.Context, apiClient flyutil.Client, appNam
409420
captureError(err)
410421

411422
if strings.Contains(err.Error(), "timed out") || strings.Contains(err.Error(), "websocket") {
412-
return nil, generateBrokenWGError(err)
423+
return nil, "", generateBrokenWGError(err)
413424
}
414425

415-
return nil, err
426+
return nil, "", err
416427
}
417428

418429
wireguardHttpClient, err := dockerclient.NewClientWithOpts(wireguardOpts...)
@@ -423,7 +434,7 @@ func newRemoteDockerClient(ctx context.Context, apiClient flyutil.Client, appNam
423434
captureError(err)
424435
tracing.RecordError(span, err, "failed to initialize remote client")
425436

426-
return nil, err
437+
return nil, "", err
427438
}
428439

429440
cachedClient = wireguardHttpClient
@@ -434,7 +445,7 @@ func newRemoteDockerClient(ctx context.Context, apiClient flyutil.Client, appNam
434445

435446
err = fmt.Errorf("failed building wgless options: %w", err)
436447
captureError(err)
437-
return nil, err
448+
return nil, "", err
438449
}
439450

440451
wireguardlessHttpsClient, err := dockerclient.NewClientWithOpts(wglessOpts...)
@@ -445,7 +456,7 @@ func newRemoteDockerClient(ctx context.Context, apiClient flyutil.Client, appNam
445456
captureError(err)
446457
tracing.RecordError(span, err, "failed to initialize wgLessHttpClient")
447458

448-
return nil, err
459+
return nil, "", err
449460
}
450461
cachedClient = wireguardlessHttpsClient
451462
}
@@ -459,18 +470,18 @@ func newRemoteDockerClient(ctx context.Context, apiClient flyutil.Client, appNam
459470
tracing.RecordError(span, err, "failed to wait for docker daemon")
460471

461472
if errors.Is(err, agent.ErrTunnelUnavailable) {
462-
return nil, generateBrokenWGError(err)
473+
return nil, "", generateBrokenWGError(err)
463474
}
464475

465-
return nil, err
476+
return nil, "", err
466477
case !up:
467478
streams.StopProgressIndicator()
468479
err := errors.New("remote builder app unavailable")
469480

470481
terminal.Warnf("Remote builder did not start in time. Check remote builder logs with `flyctl logs -a %s`\n", remoteBuilderAppName)
471482
tracing.RecordError(span, err, "remote builder failed to start")
472483

473-
return nil, err
484+
return nil, "", err
474485
default:
475486
if msg := fmt.Sprintf("Remote builder %s ready", remoteBuilderAppName); streams.IsInteractive() {
476487
streams.StopProgressIndicatorMsg(msg)
@@ -479,7 +490,7 @@ func newRemoteDockerClient(ctx context.Context, apiClient flyutil.Client, appNam
479490
}
480491
}
481492

482-
return cachedClient, nil
493+
return cachedClient, builderRegion, nil
483494
}
484495

485496
func generateBrokenWGError(err error) flyerr.GenericErr {
@@ -789,3 +800,32 @@ func (d *dockerClientFactory) IsRemote() bool {
789800
func (d *dockerClientFactory) IsLocal() bool {
790801
return !d.remote
791802
}
803+
804+
// GetBuilderRegion returns the region of the builder
805+
func (d *dockerClientFactory) GetBuilderRegion() string {
806+
return d.builderRegion
807+
}
808+
809+
// getBuilderInfo determines the builder type and region for metrics and logging
810+
func getBuilderInfo(ctx context.Context, dockerFactory *dockerClientFactory) (builderType, builderRegion string) {
811+
builderType = "local"
812+
builderRegion = "unknown"
813+
814+
if dockerFactory.IsRemote() {
815+
builderType = "remote"
816+
builderRegion = dockerFactory.GetBuilderRegion()
817+
if builderRegion == "" {
818+
builderRegion = "remote"
819+
}
820+
} else {
821+
// For local builders, try to get the nearest region
822+
apiClient := flyutil.ClientFromContext(ctx)
823+
if apiClient != nil {
824+
if nearestRegion, err := apiClient.GetNearestRegion(ctx); err == nil {
825+
builderRegion = nearestRegion.Code
826+
}
827+
}
828+
}
829+
830+
return builderType, builderRegion
831+
}

0 commit comments

Comments
 (0)