diff --git a/internal/command/apps/restart.go b/internal/command/apps/restart.go index 631f9b50e2..f814b29f67 100644 --- a/internal/command/apps/restart.go +++ b/internal/command/apps/restart.go @@ -7,12 +7,12 @@ import ( "github.com/spf13/cobra" fly "github.com/superfly/fly-go" + "github.com/superfly/fly-go/flaps" "github.com/superfly/flyctl/internal/appconfig" "github.com/superfly/flyctl/internal/command" "github.com/superfly/flyctl/internal/flag" "github.com/superfly/flyctl/internal/flag/completion" "github.com/superfly/flyctl/internal/flapsutil" - "github.com/superfly/flyctl/internal/flyutil" "github.com/superfly/flyctl/internal/machine" ) @@ -50,8 +50,8 @@ func newRestart() *cobra.Command { func runRestart(ctx context.Context) error { var ( - appName = flag.FirstArg(ctx) - client = flyutil.ClientFromContext(ctx) + appName = flag.FirstArg(ctx) + flapsClient = flapsutil.ClientFromContext(ctx) ) if appName == "" { @@ -61,16 +61,16 @@ func runRestart(ctx context.Context) error { } } - app, err := client.GetAppCompact(ctx, appName) + app, err := flapsClient.GetApp(ctx, appName) if err != nil { return err } - if app.IsPostgresApp() { + if flapsutil.IsPostgresApp(app) { return fmt.Errorf("postgres apps should use `fly pg restart` instead") } - ctx, err = BuildContext(ctx, app) + ctx, err = BuildContextForApp(ctx, app) if err != nil { return err } @@ -78,7 +78,7 @@ func runRestart(ctx context.Context) error { return runMachinesRestart(ctx, app) } -func runMachinesRestart(ctx context.Context, app *fly.AppCompact) error { +func runMachinesRestart(ctx context.Context, app *flaps.App) error { input := &fly.RestartMachineInput{ ForceStop: flag.GetBool(ctx, "force-stop"), SkipHealthChecks: flag.GetBool(ctx, "skip-health-checks"), diff --git a/internal/command/command_run.go b/internal/command/command_run.go index 8ea63f9159..4f09d259e6 100644 --- a/internal/command/command_run.go +++ b/internal/command/command_run.go @@ -416,15 +416,14 @@ func DetermineMounts(ctx context.Context, appName string, mounts []fly.MachineMo } func getUnattachedVolumes(ctx context.Context, appName, regionCode string) (map[string][]fly.Volume, error) { - apiclient := flyutil.ClientFromContext(ctx) flapsClient := flapsutil.ClientFromContext(ctx) if regionCode == "" { - region, err := apiclient.GetNearestRegion(ctx) + regionData, err := flapsClient.GetRegions(ctx) if err != nil { return nil, err } - regionCode = region.Code + regionCode = regionData.Nearest } volumes, err := flapsClient.GetVolumes(ctx, appName) diff --git a/internal/command/console/console.go b/internal/command/console/console.go index f951ef780d..bb4807421d 100644 --- a/internal/command/console/console.go +++ b/internal/command/console/console.go @@ -180,10 +180,11 @@ func runConsole(ctx context.Context) error { return fmt.Errorf("failed to get app: %w", err) } - network, err := apiClient.GetAppNetwork(ctx, app.Name) + flapsApp, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, app.Name) if err != nil { return fmt.Errorf("failed to get app network: %w", err) } + network := flapsutil.NetworkName(flapsApp) appConfig := appconfig.ConfigFromContext(ctx) if appConfig == nil { @@ -208,7 +209,7 @@ func runConsole(ctx context.Context) error { defer cleanup() } - _, dialer, err := agent.BringUpAgent(ctx, apiClient, app, *network, false) + _, dialer, err := agent.BringUpAgent(ctx, apiClient, app, network, false) if err != nil { return err } diff --git a/internal/command/curl/curl.go b/internal/command/curl/curl.go index 622ae9e2d3..659c71cf92 100644 --- a/internal/command/curl/curl.go +++ b/internal/command/curl/curl.go @@ -23,7 +23,7 @@ import ( "github.com/superfly/flyctl/internal/command" "github.com/superfly/flyctl/internal/config" "github.com/superfly/flyctl/internal/flag" - "github.com/superfly/flyctl/internal/flyutil" + "github.com/superfly/flyctl/internal/flapsutil" "github.com/superfly/flyctl/internal/render" "github.com/superfly/flyctl/iostreams" ) @@ -79,17 +79,16 @@ func run(ctx context.Context) error { } func fetchRegionCodes(ctx context.Context) (codes []string, err error) { - client := flyutil.ClientFromContext(ctx) + flapsClient := flapsutil.ClientFromContext(ctx) - var regions []fly.Region - if regions, _, err = client.PlatformRegions(ctx); err != nil { - err = fmt.Errorf("failed retrieving regions: %w", err) - - return - } else if len(regions) == 0 { - err = errors.New("no regions could be retrieved") + regionData, err := flapsClient.GetRegions(ctx) + if err != nil { + return nil, fmt.Errorf("failed retrieving regions: %w", err) + } - return + regions := regionData.Regions + if len(regions) == 0 { + return nil, errors.New("no regions could be retrieved") } // Filter out deprecated regions diff --git a/internal/command/dashboard/root.go b/internal/command/dashboard/root.go index 1a71131c31..1f6815d7fb 100644 --- a/internal/command/dashboard/root.go +++ b/internal/command/dashboard/root.go @@ -9,7 +9,7 @@ import ( "github.com/superfly/flyctl/internal/appconfig" "github.com/superfly/flyctl/internal/command" "github.com/superfly/flyctl/internal/flag" - "github.com/superfly/flyctl/internal/flyutil" + "github.com/superfly/flyctl/internal/flapsutil" "github.com/superfly/flyctl/iostreams" ) @@ -67,13 +67,12 @@ func runDashboardMetrics(ctx context.Context) error { appName := appconfig.NameFromContext(ctx) if flag.GetBool(ctx, "grafana") { - client := flyutil.ClientFromContext(ctx) - app, err := client.GetAppBasic(ctx, appName) + app, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, appName) if err != nil { return fmt.Errorf("failed to get app info: %w", err) } - url := fmt.Sprintf("https://fly-metrics.net/d/fly-app/fly-app?orgId=%s&var-app=%s", app.Organization.InternalNumericID, appName) + url := fmt.Sprintf("https://fly-metrics.net/d/fly-app/fly-app?orgId=%d&var-app=%s", app.Organization.InternalNumericID, appName) return runDashboardOpen(ctx, url) } diff --git a/internal/command/dig/dig.go b/internal/command/dig/dig.go index 8244792831..3ca5aa323b 100644 --- a/internal/command/dig/dig.go +++ b/internal/command/dig/dig.go @@ -15,6 +15,7 @@ import ( "github.com/spf13/cobra" "github.com/superfly/flyctl/agent" + "github.com/superfly/flyctl/internal/flapsutil" "github.com/superfly/flyctl/iostreams" "github.com/superfly/flyctl/internal/appconfig" @@ -74,7 +75,7 @@ func run(ctx context.Context) error { if orgSlug == "" { appName := appconfig.NameFromContext(ctx) - app, err := client.GetAppBasic(ctx, appName) + app, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, appName) if err != nil { return fmt.Errorf("get app: %w", err) } diff --git a/internal/command/image/show.go b/internal/command/image/show.go index 1d9c1b27f0..7fce70b8e1 100644 --- a/internal/command/image/show.go +++ b/internal/command/image/show.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/cobra" fly "github.com/superfly/fly-go" + "github.com/superfly/fly-go/flaps" "github.com/superfly/flyctl/internal/appconfig" "github.com/superfly/flyctl/internal/command" "github.com/superfly/flyctl/internal/config" @@ -44,11 +45,10 @@ func newShow() *cobra.Command { func runShow(ctx context.Context) error { var ( - client = flyutil.ClientFromContext(ctx) appName = appconfig.NameFromContext(ctx) ) - app, err := client.GetAppCompact(ctx, appName) + app, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, appName) if err != nil { return fmt.Errorf("get app: %w", err) } @@ -56,7 +56,7 @@ func runShow(ctx context.Context) error { return showMachineImage(ctx, app) } -func showMachineImage(ctx context.Context, app *fly.AppCompact) error { +func showMachineImage(ctx context.Context, app *flaps.App) error { var ( io = iostreams.FromContext(ctx) colorize = io.ColorScheme() @@ -158,7 +158,7 @@ func showMachineImage(ctx context.Context, app *fly.AppCompact) error { latest = latestImage } - if app.IsPostgresApp() { + if flapsutil.IsPostgresApp(app) { // Abort if we detect a postgres machine running a different major version. if latest.Tag != latestImage.Tag { return fmt.Errorf("major version mismatch detected") diff --git a/internal/command/image/update.go b/internal/command/image/update.go index f64e7aaa9b..5ffcf7a88a 100644 --- a/internal/command/image/update.go +++ b/internal/command/image/update.go @@ -10,7 +10,7 @@ import ( "github.com/superfly/flyctl/internal/command" "github.com/superfly/flyctl/internal/command/apps" "github.com/superfly/flyctl/internal/flag" - "github.com/superfly/flyctl/internal/flyutil" + "github.com/superfly/flyctl/internal/flapsutil" ) func newUpdate() *cobra.Command { @@ -49,20 +49,19 @@ The update will perform a rolling restart against each Machine, which may result func runUpdate(ctx context.Context) error { var ( appName = appconfig.NameFromContext(ctx) - client = flyutil.ClientFromContext(ctx) ) - app, err := client.GetAppCompact(ctx, appName) + app, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, appName) if err != nil { return fmt.Errorf("get app: %w", err) } - ctx, err = apps.BuildContext(ctx, app) + ctx, err = apps.BuildContextForApp(ctx, app) if err != nil { return err } - if app.IsPostgresApp() { + if flapsutil.IsPostgresApp(app) { return updatePostgresOnMachines(ctx, app) } diff --git a/internal/command/image/update_machines.go b/internal/command/image/update_machines.go index 97f905db44..4a91c02350 100644 --- a/internal/command/image/update_machines.go +++ b/internal/command/image/update_machines.go @@ -6,6 +6,7 @@ import ( "strings" fly "github.com/superfly/fly-go" + "github.com/superfly/fly-go/flaps" "github.com/superfly/flyctl/agent" "github.com/superfly/flyctl/flypg" "github.com/superfly/flyctl/internal/appsecrets" @@ -15,7 +16,7 @@ import ( "github.com/superfly/flyctl/iostreams" ) -func updateImageForMachines(ctx context.Context, app *fly.AppCompact) error { +func updateImageForMachines(ctx context.Context, app *flaps.App) error { var ( io = iostreams.FromContext(ctx) @@ -83,7 +84,7 @@ type member struct { TargetConfig fly.MachineConfig } -func updatePostgresOnMachines(ctx context.Context, app *fly.AppCompact) (err error) { +func updatePostgresOnMachines(ctx context.Context, app *flaps.App) (err error) { var ( io = iostreams.FromContext(ctx) colorize = io.ColorScheme() diff --git a/internal/command/launch/launch_databases.go b/internal/command/launch/launch_databases.go index df0606c347..9dfba0129c 100644 --- a/internal/command/launch/launch_databases.go +++ b/internal/command/launch/launch_databases.go @@ -77,9 +77,8 @@ func (state *launchState) createDatabases(ctx context.Context) error { func (state *launchState) createFlyPostgres(ctx context.Context) error { var ( - pgPlan = state.Plan.Postgres.FlyPostgres - apiClient = flyutil.ClientFromContext(ctx) - io = iostreams.FromContext(ctx) + pgPlan = state.Plan.Postgres.FlyPostgres + io = iostreams.FromContext(ctx) ) attachToExisting := false @@ -88,12 +87,8 @@ func (state *launchState) createFlyPostgres(ctx context.Context) error { pgPlan.AppName = fmt.Sprintf("%s-db", state.appConfig.AppName) } - if apps, err := apiClient.GetApps(ctx, nil); err == nil { - for _, app := range apps { - if app.Name == pgPlan.AppName { - attachToExisting = true - } - } + if _, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, pgPlan.AppName); err == nil { + attachToExisting = true } if attachToExisting { @@ -486,11 +481,12 @@ func (state *launchState) createUpstashRedis(ctx context.Context) error { var readReplicaRegions []fly.Region { - client := flyutil.ClientFromContext(ctx) - regions, _, err := client.PlatformRegions(ctx) + flapsClient := flapsutil.ClientFromContext(ctx) + regionData, err := flapsClient.GetRegions(ctx) if err != nil { return err } + regions := regionData.Regions // Filter out deprecated regions regions = lo.Filter(regions, func(r fly.Region, _ int) bool { return !r.Deprecated diff --git a/internal/command/launch/plan/postgres_test.go b/internal/command/launch/plan/postgres_test.go index 2dcd76baf9..34d5a6fd93 100644 --- a/internal/command/launch/plan/postgres_test.go +++ b/internal/command/launch/plan/postgres_test.go @@ -173,36 +173,29 @@ func TestDefaultPostgres_ForceTypes(t *testing.T) { ctx = flagctx.NewContext(ctx, flagSet) // Set up mock flaps client for MPG region availability - var mpgRegions []fly.Region + // Platform regions come from Flaps; MPGAvailable marks MPG region support. + var regions []fly.Region if tt.mpgRegionsWithIAD { - mpgRegions = []fly.Region{ - {Code: "iad", MPGAvailable: true}, - {Code: "lax", MPGAvailable: true}, + regions = []fly.Region{ + {Code: "iad", Name: "Ashburn, Virginia (US)", MPGAvailable: true}, + {Code: "lax", Name: "Los Angeles, California (US)", MPGAvailable: true}, + {Code: "fra", Name: "Frankfurt, Germany"}, } } else { - mpgRegions = []fly.Region{ - {Code: "lax", MPGAvailable: true}, - {Code: "fra", MPGAvailable: true}, - // iad is not in the list, so it's not available + regions = []fly.Region{ + {Code: "iad", Name: "Ashburn, Virginia (US)"}, // iad is not MPG-available + {Code: "lax", Name: "Los Angeles, California (US)", MPGAvailable: true}, + {Code: "fra", Name: "Frankfurt, Germany", MPGAvailable: true}, } } ctx = flapsutil.NewContextWithClient(ctx, &mock.FlapsClient{ GetRegionsFunc: func(ctx context.Context) (*flaps.RegionData, error) { - return &flaps.RegionData{Regions: mpgRegions}, nil + return &flaps.RegionData{Regions: regions, Nearest: "iad"}, nil }, }) - // Set up mock API client for platform regions mockClient := &mock.Client{ - PlatformRegionsFunc: func(ctx context.Context) ([]fly.Region, *fly.Region, error) { - // Return some mock regions for testing - return []fly.Region{ - {Code: "iad", Name: "Ashburn, Virginia (US)"}, - {Code: "lax", Name: "Los Angeles, California (US)"}, - {Code: "fra", Name: "Frankfurt, Germany"}, - }, &fly.Region{Code: "iad", Name: "Ashburn, Virginia (US)"}, nil - }, GenqClientFunc: func() genq.Client { return &mockGenqClient{} }, @@ -269,15 +262,17 @@ func TestDefaultPostgres_RegionSwitching(t *testing.T) { mockUIEX := &mockUIEXClient{} ctx = uiexutil.NewContextWithClient(ctx, mockUIEX) - // Set up mock API client for platform regions - mockClient := &mock.Client{ - PlatformRegionsFunc: func(ctx context.Context) ([]fly.Region, *fly.Region, error) { - return []fly.Region{ + ctx = flapsutil.NewContextWithClient(ctx, &mock.FlapsClient{ + GetRegionsFunc: func(ctx context.Context) (*flaps.RegionData, error) { + return &flaps.RegionData{Regions: []fly.Region{ {Code: "iad", Name: "Ashburn, Virginia (US)"}, - {Code: "lax", Name: "Los Angeles, California (US)"}, - {Code: "fra", Name: "Frankfurt, Germany"}, - }, &fly.Region{Code: "iad", Name: "Ashburn, Virginia (US)"}, nil + {Code: "lax", Name: "Los Angeles, California (US)", MPGAvailable: true}, + {Code: "fra", Name: "Frankfurt, Germany", MPGAvailable: true}, + }, Nearest: "iad"}, nil }, + }) + + mockClient := &mock.Client{ GenqClientFunc: func() genq.Client { return &mockGenqClient{} }, diff --git a/internal/command/launch/state.go b/internal/command/launch/state.go index 0757919a13..f6bbf00187 100644 --- a/internal/command/launch/state.go +++ b/internal/command/launch/state.go @@ -11,6 +11,7 @@ import ( "github.com/superfly/flyctl/gql" "github.com/superfly/flyctl/internal/appconfig" "github.com/superfly/flyctl/internal/command/launch/plan" + "github.com/superfly/flyctl/internal/flapsutil" "github.com/superfly/flyctl/internal/flyutil" "github.com/superfly/flyctl/iostreams" ) @@ -93,12 +94,13 @@ func (state *launchState) Org(ctx context.Context) (*fly.Organization, error) { } func (state *launchState) Region(ctx context.Context) (fly.Region, error) { - apiClient := flyutil.ClientFromContext(ctx) + flapsClient := flapsutil.ClientFromContext(ctx) regions, err := cacheGrab(state.cache, "regions", func() ([]fly.Region, error) { - regions, _, err := apiClient.PlatformRegions(ctx) + regionData, err := flapsClient.GetRegions(ctx) if err != nil { return nil, err } + regions := regionData.Regions // Filter out deprecated regions regions = lo.Filter(regions, func(r fly.Region, _ int) bool { return !r.Deprecated diff --git a/internal/command/machine/destroy.go b/internal/command/machine/destroy.go index 5a33cc08af..548840be52 100644 --- a/internal/command/machine/destroy.go +++ b/internal/command/machine/destroy.go @@ -11,7 +11,6 @@ import ( "github.com/superfly/flyctl/internal/command" "github.com/superfly/flyctl/internal/flag" "github.com/superfly/flyctl/internal/flapsutil" - "github.com/superfly/flyctl/internal/flyutil" mach "github.com/superfly/flyctl/internal/machine" "github.com/superfly/flyctl/internal/prompt" "github.com/superfly/flyctl/iostreams" @@ -141,8 +140,7 @@ func singleDestroyRun(ctx context.Context, machine *fly.Machine) error { appName := appconfig.NameFromContext(ctx) // This is used for the deletion hook below. - client := flyutil.ClientFromContext(ctx) - app, err := client.GetAppCompact(ctx, appName) + app, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, appName) if err != nil { return fmt.Errorf("could not get app '%s': %w", appName, err) } diff --git a/internal/command/machine/run.go b/internal/command/machine/run.go index 9cf4581176..b53546c13f 100644 --- a/internal/command/machine/run.go +++ b/internal/command/machine/run.go @@ -381,10 +381,11 @@ func runMachineRun(ctx context.Context) error { } } - network, err := client.GetAppNetwork(ctx, app.Name) + flapsApp, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, app.Name) if err != nil { return err } + network := flapsutil.NetworkName(flapsApp) machineConf := &fly.MachineConfig{ AutoDestroy: destroy, @@ -478,7 +479,7 @@ func runMachineRun(ctx context.Context) error { } if interact { - _, dialer, err := agent.BringUpAgent(ctx, client, app, *network, false) + _, dialer, err := agent.BringUpAgent(ctx, client, app, network, false) if err != nil { return err } diff --git a/internal/command/ping/ping.go b/internal/command/ping/ping.go index db95ffe040..e25d456077 100644 --- a/internal/command/ping/ping.go +++ b/internal/command/ping/ping.go @@ -19,6 +19,7 @@ import ( "github.com/superfly/flyctl/internal/command" "github.com/superfly/flyctl/internal/command/dig" "github.com/superfly/flyctl/internal/flag" + "github.com/superfly/flyctl/internal/flapsutil" "github.com/superfly/flyctl/internal/flyutil" "golang.org/x/net/icmp" "golang.org/x/net/ipv6" @@ -101,7 +102,7 @@ func run(ctx context.Context) error { if orgSlug == "" { appName := appconfig.NameFromContext(ctx) - app, err := client.GetAppBasic(ctx, appName) + app, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, appName) if err != nil { return fmt.Errorf("get app: %w", err) } diff --git a/internal/command/postgres/add_flycast.go b/internal/command/postgres/add_flycast.go index d96b73683f..de119e354e 100644 --- a/internal/command/postgres/add_flycast.go +++ b/internal/command/postgres/add_flycast.go @@ -11,7 +11,7 @@ import ( "github.com/superfly/flyctl/internal/command" "github.com/superfly/flyctl/internal/command/apps" "github.com/superfly/flyctl/internal/flag" - "github.com/superfly/flyctl/internal/flyutil" + "github.com/superfly/flyctl/internal/flapsutil" mach "github.com/superfly/flyctl/internal/machine" "github.com/superfly/flyctl/internal/prompt" ) @@ -42,20 +42,19 @@ func newAddFlycast() *cobra.Command { func runAddFlycast(ctx context.Context) error { var ( - client = flyutil.ClientFromContext(ctx) appName = appconfig.NameFromContext(ctx) ) - app, err := client.GetAppCompact(ctx, appName) + app, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, appName) if err != nil { return fmt.Errorf("failed retrieving app %s: %w", appName, err) } - if !app.IsPostgresApp() { + if !flapsutil.IsPostgresApp(app) { return fmt.Errorf("app %s is not a postgres app", appName) } - ctx, err = apps.BuildContext(ctx, app) + ctx, err = apps.BuildContextForApp(ctx, app) if err != nil { return err } diff --git a/internal/command/postgres/attach.go b/internal/command/postgres/attach.go index 7471aa7800..dbf5761c16 100644 --- a/internal/command/postgres/attach.go +++ b/internal/command/postgres/attach.go @@ -74,27 +74,27 @@ func newAttach() *cobra.Command { func runAttach(ctx context.Context) error { var ( - pgAppName = flag.FirstArg(ctx) - appName = appconfig.NameFromContext(ctx) - client = flyutil.ClientFromContext(ctx) + pgAppName = flag.FirstArg(ctx) + appName = appconfig.NameFromContext(ctx) + flapsClient = flapsutil.ClientFromContext(ctx) ) - pgApp, err := client.GetAppCompact(ctx, pgAppName) + pgApp, err := flapsClient.GetApp(ctx, pgAppName) if err != nil { return fmt.Errorf("failed retrieving postgres app %s: %w", pgAppName, err) } - if !pgApp.IsPostgresApp() { + if !flapsutil.IsPostgresApp(pgApp) { return fmt.Errorf("app %s is not a postgres app", pgAppName) } - app, err := client.GetAppCompact(ctx, appName) + app, err := flapsClient.GetApp(ctx, appName) if err != nil { return fmt.Errorf("failed retrieving app %s: %w", appName, err) } // Build context around the postgres app - ctx, err = apps.BuildContext(ctx, pgApp) + ctx, err = apps.BuildContextForApp(ctx, pgApp) if err != nil { return err } @@ -120,28 +120,28 @@ func runAttach(ctx context.Context) error { // AttachCluster is mean't to be called from an external package. func AttachCluster(ctx context.Context, params AttachParams) error { var ( - client = flyutil.ClientFromContext(ctx) + flapsClient = flapsutil.ClientFromContext(ctx) pgAppName = params.PgAppName appName = params.AppName ) - pgApp, err := client.GetAppCompact(ctx, pgAppName) + pgApp, err := flapsClient.GetApp(ctx, pgAppName) if err != nil { return fmt.Errorf("failed retrieving postgres app %s: %w", pgAppName, err) } - if !pgApp.IsPostgresApp() { + if !flapsutil.IsPostgresApp(pgApp) { return fmt.Errorf("app %s is not a postgres app", pgAppName) } - ctx, err = apps.BuildContext(ctx, pgApp) + ctx, err = apps.BuildContextForApp(ctx, pgApp) if err != nil { return err } // Verify that the target app exists. - _, err = client.GetAppBasic(ctx, appName) + _, err = flapsClient.GetApp(ctx, appName) if err != nil { return fmt.Errorf("failed retrieving app %s: %w", appName, err) } diff --git a/internal/command/postgres/backup.go b/internal/command/postgres/backup.go index 7e264473d1..ceb849c1ee 100644 --- a/internal/command/postgres/backup.go +++ b/internal/command/postgres/backup.go @@ -292,14 +292,14 @@ func runBackupEnable(ctx context.Context) error { client = flyutil.ClientFromContext(ctx) ) - app, err := client.GetAppCompact(ctx, appName) + flapsClient := flapsutil.ClientFromContext(ctx) + + app, err := flapsClient.GetApp(ctx, appName) if err != nil { return err } - flapsClient := flapsutil.ClientFromContext(ctx) - - if !app.IsPostgresApp() { + if !flapsutil.IsPostgresApp(app) { return fmt.Errorf("app %s is not a postgres app", appName) } diff --git a/internal/command/postgres/config_show.go b/internal/command/postgres/config_show.go index 449b704c71..ecb2cfc026 100644 --- a/internal/command/postgres/config_show.go +++ b/internal/command/postgres/config_show.go @@ -7,14 +7,14 @@ import ( "strings" "github.com/spf13/cobra" - fly "github.com/superfly/fly-go" + "github.com/superfly/fly-go/flaps" "github.com/superfly/flyctl/agent" "github.com/superfly/flyctl/flypg" "github.com/superfly/flyctl/internal/appconfig" "github.com/superfly/flyctl/internal/command" "github.com/superfly/flyctl/internal/command/apps" "github.com/superfly/flyctl/internal/flag" - "github.com/superfly/flyctl/internal/flyutil" + "github.com/superfly/flyctl/internal/flapsutil" mach "github.com/superfly/flyctl/internal/machine" "github.com/superfly/flyctl/internal/render" "github.com/superfly/flyctl/iostreams" @@ -44,20 +44,19 @@ func newConfigShow() (cmd *cobra.Command) { func runConfigShow(ctx context.Context) error { var ( - client = flyutil.ClientFromContext(ctx) appName = appconfig.NameFromContext(ctx) ) - app, err := client.GetAppCompact(ctx, appName) + app, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, appName) if err != nil { return fmt.Errorf("failed retrieving app %s: %w", appName, err) } - if !app.IsPostgresApp() { + if !flapsutil.IsPostgresApp(app) { return fmt.Errorf("app %s is not a postgres app", appName) } - ctx, err = apps.BuildContext(ctx, app) + ctx, err = apps.BuildContextForApp(ctx, app) if err != nil { return err } @@ -65,14 +64,14 @@ func runConfigShow(ctx context.Context) error { return runMachineConfigShow(ctx, app) } -func runMachineConfigShow(ctx context.Context, app *fly.AppCompact) (err error) { +func runMachineConfigShow(ctx context.Context, app *flaps.App) (err error) { var ( MinPostgresHaVersion = "0.0.19" MinPostgresStandaloneVersion = "0.0.7" MinPostgresFlexVersion = "0.0.3" ) - ctx, err = apps.BuildContext(ctx, app) + ctx, err = apps.BuildContextForApp(ctx, app) if err != nil { return err } @@ -99,7 +98,7 @@ func runMachineConfigShow(ctx context.Context, app *fly.AppCompact) (err error) return showSettings(ctx, app, manager, leader.PrivateIP) } -func showSettings(ctx context.Context, app *fly.AppCompact, manager string, leaderIP string) error { +func showSettings(ctx context.Context, app *flaps.App, manager string, leaderIP string) error { var ( io = iostreams.FromContext(ctx) colorize = io.ColorScheme() diff --git a/internal/command/postgres/create.go b/internal/command/postgres/create.go index 1d9c041aee..d973745612 100644 --- a/internal/command/postgres/create.go +++ b/internal/command/postgres/create.go @@ -104,10 +104,10 @@ func newCreate() *cobra.Command { // be safely passed through from other commands. func run(ctx context.Context) (err error) { var ( - appName = flag.GetString(ctx, "name") - client = flyutil.ClientFromContext(ctx) - io = iostreams.FromContext(ctx) - colorize = io.ColorScheme() + appName = flag.GetString(ctx, "name") + flapsClient = flapsutil.ClientFromContext(ctx) + io = iostreams.FromContext(ctx) + colorize = io.ColorScheme() ) // pre-fetch platform regions for later use @@ -170,17 +170,17 @@ func run(ctx context.Context) (err error) { } // Resolve specified fork-from app - forkApp, err := client.GetAppCompact(ctx, forkSlice[0]) + forkApp, err := flapsClient.GetApp(ctx, forkSlice[0]) if err != nil { return fmt.Errorf("Failed to resolve the specified fork-from app %s: %w", forkSlice[0], err) } // Confirm fork-app is a postgres app - if !forkApp.IsPostgresApp() { + if !flapsutil.IsPostgresApp(forkApp) { return fmt.Errorf("The fork-from app %q must be a postgres app", forkApp.Name) } - ctx, err := apps.BuildContext(ctx, forkApp) + ctx, err := apps.BuildContextForApp(ctx, forkApp) if err != nil { return err } diff --git a/internal/command/postgres/db.go b/internal/command/postgres/db.go index 39ac6a7998..3c49a44335 100644 --- a/internal/command/postgres/db.go +++ b/internal/command/postgres/db.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/spf13/cobra" - fly "github.com/superfly/fly-go" + "github.com/superfly/fly-go/flaps" "github.com/superfly/flyctl/agent" "github.com/superfly/flyctl/flypg" "github.com/superfly/flyctl/internal/appconfig" @@ -14,7 +14,7 @@ import ( "github.com/superfly/flyctl/internal/command/apps" "github.com/superfly/flyctl/internal/config" "github.com/superfly/flyctl/internal/flag" - "github.com/superfly/flyctl/internal/flyutil" + "github.com/superfly/flyctl/internal/flapsutil" mach "github.com/superfly/flyctl/internal/machine" "github.com/superfly/flyctl/internal/render" "github.com/superfly/flyctl/iostreams" @@ -63,20 +63,19 @@ func newListDbs() *cobra.Command { func runListDbs(ctx context.Context) error { var ( - client = flyutil.ClientFromContext(ctx) appName = appconfig.NameFromContext(ctx) ) - app, err := client.GetAppCompact(ctx, appName) + app, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, appName) if err != nil { return fmt.Errorf("failed retrieving app %s: %w", appName, err) } - if !app.IsPostgresApp() { + if !flapsutil.IsPostgresApp(app) { return fmt.Errorf("app %s is not a postgres app", appName) } - ctx, err = apps.BuildContext(ctx, app) + ctx, err = apps.BuildContextForApp(ctx, app) if err != nil { return err } @@ -84,7 +83,7 @@ func runListDbs(ctx context.Context) error { return runMachineListDbs(ctx, app) } -func runMachineListDbs(ctx context.Context, app *fly.AppCompact) error { +func runMachineListDbs(ctx context.Context, app *flaps.App) error { var ( MinPostgresHaVersion = "0.0.19" MinPostgresFlexVersion = "0.0.3" diff --git a/internal/command/postgres/restart.go b/internal/command/postgres/restart.go index dbc0e489e0..edd8c8c2e2 100644 --- a/internal/command/postgres/restart.go +++ b/internal/command/postgres/restart.go @@ -12,7 +12,7 @@ import ( "github.com/superfly/flyctl/internal/command" "github.com/superfly/flyctl/internal/command/apps" "github.com/superfly/flyctl/internal/flag" - "github.com/superfly/flyctl/internal/flyutil" + "github.com/superfly/flyctl/internal/flapsutil" mach "github.com/superfly/flyctl/internal/machine" "github.com/superfly/flyctl/iostreams" ) @@ -50,19 +50,18 @@ func newRestart() *cobra.Command { func runRestart(ctx context.Context) error { var ( appName = appconfig.NameFromContext(ctx) - client = flyutil.ClientFromContext(ctx) ) - app, err := client.GetAppCompact(ctx, appName) + app, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, appName) if err != nil { return err } - if !app.IsPostgresApp() { + if !flapsutil.IsPostgresApp(app) { return fmt.Errorf("app %s is not a postgres app", appName) } - ctx, err = apps.BuildContext(ctx, app) + ctx, err = apps.BuildContextForApp(ctx, app) if err != nil { return err } diff --git a/internal/command/postgres/users.go b/internal/command/postgres/users.go index 8329c59b52..0e25244ca1 100644 --- a/internal/command/postgres/users.go +++ b/internal/command/postgres/users.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/spf13/cobra" - fly "github.com/superfly/fly-go" + "github.com/superfly/fly-go/flaps" "github.com/superfly/flyctl/agent" "github.com/superfly/flyctl/flypg" "github.com/superfly/flyctl/internal/appconfig" @@ -14,7 +14,7 @@ import ( "github.com/superfly/flyctl/internal/command/apps" "github.com/superfly/flyctl/internal/config" "github.com/superfly/flyctl/internal/flag" - "github.com/superfly/flyctl/internal/flyutil" + "github.com/superfly/flyctl/internal/flapsutil" mach "github.com/superfly/flyctl/internal/machine" "github.com/superfly/flyctl/internal/render" "github.com/superfly/flyctl/iostreams" @@ -64,20 +64,19 @@ func newListUsers() *cobra.Command { func runListUsers(ctx context.Context) error { var ( - client = flyutil.ClientFromContext(ctx) appName = appconfig.NameFromContext(ctx) ) - app, err := client.GetAppCompact(ctx, appName) + app, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, appName) if err != nil { return fmt.Errorf("failed retrieving app %s: %w", appName, err) } - if !app.IsPostgresApp() { + if !flapsutil.IsPostgresApp(app) { return fmt.Errorf("app %s is not a postgres app", appName) } - ctx, err = apps.BuildContext(ctx, app) + ctx, err = apps.BuildContextForApp(ctx, app) if err != nil { return err } @@ -85,7 +84,7 @@ func runListUsers(ctx context.Context) error { return runMachineListUsers(ctx, app) } -func runMachineListUsers(ctx context.Context, app *fly.AppCompact) (err error) { +func runMachineListUsers(ctx context.Context, app *flaps.App) (err error) { // Minimum image version requirements var ( MinPostgresHaVersion = "0.0.19" diff --git a/internal/command/proxy/proxy.go b/internal/command/proxy/proxy.go index 82ba34c8ac..0c9657eaf6 100644 --- a/internal/command/proxy/proxy.go +++ b/internal/command/proxy/proxy.go @@ -13,6 +13,7 @@ import ( "github.com/superfly/flyctl/internal/command" "github.com/superfly/flyctl/internal/flag" "github.com/superfly/flyctl/internal/flag/flagnames" + "github.com/superfly/flyctl/internal/flapsutil" "github.com/superfly/flyctl/internal/flyutil" "github.com/superfly/flyctl/internal/prompt" "github.com/superfly/flyctl/iostreams" @@ -90,18 +91,14 @@ func run(ctx context.Context) (err error) { orgSlug = org.Slug } - network, err := client.GetAppNetwork(ctx, appName) - if err != nil { - return err - } - - // var app *fly.App + var network string if appName != "" { - app, err := client.GetAppBasic(ctx, appName) + app, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, appName) if err != nil { return err } orgSlug = app.Organization.Slug + network = flapsutil.NetworkName(app) } agentclient, err := agent.Establish(ctx, client) @@ -110,12 +107,12 @@ func run(ctx context.Context) (err error) { } // do this explicitly so we can get the DNS server address - _, err = agentclient.Establish(ctx, orgSlug, *network) + _, err = agentclient.Establish(ctx, orgSlug, network) if err != nil { return err } - dialer, err := agentclient.ConnectToTunnel(ctx, orgSlug, *network, flag.GetBool(ctx, "quiet")) + dialer, err := agentclient.ConnectToTunnel(ctx, orgSlug, network, flag.GetBool(ctx, "quiet")) if err != nil { return err } @@ -129,7 +126,7 @@ func run(ctx context.Context) (err error) { OrganizationSlug: orgSlug, Dialer: dialer, PromptInstance: promptInstance, - Network: *network, + Network: network, } if len(args) > 1 { diff --git a/internal/command/ssh/console.go b/internal/command/ssh/console.go index ff9a8b9fb9..7ea95ef4d8 100644 --- a/internal/command/ssh/console.go +++ b/internal/command/ssh/console.go @@ -175,12 +175,12 @@ func runConsole(ctx context.Context) error { return fmt.Errorf("get app: %w", err) } - network, err := client.GetAppNetwork(ctx, app.Name) + flapsApp, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, app.Name) if err != nil { return fmt.Errorf("get app network: %w", err) } - agentclient, dialer, err := agent.BringUpAgent(ctx, client, app, *network, quiet(ctx)) + agentclient, dialer, err := agent.BringUpAgent(ctx, client, app, flapsutil.NetworkName(flapsApp), quiet(ctx)) if err != nil { return err } diff --git a/internal/command/ssh/sftp.go b/internal/command/ssh/sftp.go index 461641bf33..b8b12f10e8 100644 --- a/internal/command/ssh/sftp.go +++ b/internal/command/ssh/sftp.go @@ -19,6 +19,7 @@ import ( "github.com/superfly/flyctl/internal/appconfig" "github.com/superfly/flyctl/internal/command" "github.com/superfly/flyctl/internal/flag" + "github.com/superfly/flyctl/internal/flapsutil" "github.com/superfly/flyctl/internal/flyutil" "github.com/chzyer/readline" @@ -137,12 +138,12 @@ func newSFTPConnection(ctx context.Context) (*sftp.Client, error) { return nil, fmt.Errorf("get app: %w", err) } - network, err := client.GetAppNetwork(ctx, appName) + flapsApp, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, appName) if err != nil { return nil, fmt.Errorf("get app network: %w", err) } - agentclient, dialer, err := agent.BringUpAgent(ctx, client, app, *network, quiet(ctx)) + agentclient, dialer, err := agent.BringUpAgent(ctx, client, app, flapsutil.NetworkName(flapsApp), quiet(ctx)) if err != nil { return nil, err } diff --git a/internal/command/tokens/list.go b/internal/command/tokens/list.go index f4e484df8f..d9b5842a45 100644 --- a/internal/command/tokens/list.go +++ b/internal/command/tokens/list.go @@ -10,6 +10,7 @@ import ( "github.com/superfly/flyctl/internal/command" "github.com/superfly/flyctl/internal/command/orgs" "github.com/superfly/flyctl/internal/flag" + "github.com/superfly/flyctl/internal/flapsutil" "github.com/superfly/flyctl/internal/flyutil" "github.com/superfly/flyctl/internal/render" "github.com/superfly/flyctl/iostreams" @@ -69,7 +70,7 @@ func runList(ctx context.Context) (err error) { // --org passed must match the selected app's org if orgFlag != "" { // Get app details, so we can identify its organization slug - app, err := apiClient.GetAppCompact(ctx, appName) + app, err := flapsutil.ClientFromContext(ctx).GetApp(ctx, appName) if err != nil { return fmt.Errorf("failed retrieving app %s: %w", appName, err) } @@ -80,8 +81,10 @@ func runList(ctx context.Context) (err error) { return fmt.Errorf("failed retrieving org %w", err) } - // Throw an error if app's org slug does not match --org slug - if app.Organization.Slug != org.Slug { + // Throw an error if app's org slug does not match --org slug. + // Flaps reports the raw org slug, while the selected org may carry + // the "personal" alias. + if app.Organization.Slug != org.RawSlug && app.Organization.Slug != org.Slug { return fmt.Errorf("failed to retrieve tokens, selected application \"%s\" does not belong to selected organization \"%s\"", appName, org.Slug) } } diff --git a/internal/command/volumes/destroy.go b/internal/command/volumes/destroy.go index 58d6d3da9c..3b92db4ddd 100644 --- a/internal/command/volumes/destroy.go +++ b/internal/command/volumes/destroy.go @@ -61,11 +61,10 @@ func runDestroy(ctx context.Context) error { flapsClient := flapsutil.ClientFromContext(ctx) if len(volIDs) == 0 { - app, err := client.GetAppBasic(ctx, appName) - if err != nil { + if _, err := flapsClient.GetApp(ctx, appName); err != nil { return err } - volume, err := selectVolume(ctx, flapsClient, app) + volume, err := selectVolume(ctx, flapsClient, appName) if err != nil { return err } diff --git a/internal/command/volumes/extend.go b/internal/command/volumes/extend.go index ec3ca6101c..00de7e01c5 100644 --- a/internal/command/volumes/extend.go +++ b/internal/command/volumes/extend.go @@ -12,7 +12,6 @@ import ( "github.com/superfly/flyctl/internal/config" "github.com/superfly/flyctl/internal/flag" "github.com/superfly/flyctl/internal/flapsutil" - "github.com/superfly/flyctl/internal/flyutil" "github.com/superfly/flyctl/internal/render" "github.com/superfly/flyctl/iostreams" ) @@ -55,14 +54,12 @@ func runExtend(ctx context.Context) error { io = iostreams.FromContext(ctx) colorize = io.ColorScheme() appName = appconfig.NameFromContext(ctx) - client = flyutil.ClientFromContext(ctx) volID = flag.FirstArg(ctx) ) flapsClient := flapsutil.ClientFromContext(ctx) - app, err := client.GetAppBasic(ctx, appName) - if err != nil { + if _, err := flapsClient.GetApp(ctx, appName); err != nil { return err } @@ -85,7 +82,7 @@ func runExtend(ctx context.Context) error { } if volID == "" { - volume, err := selectVolume(ctx, flapsClient, app) + volume, err := selectVolume(ctx, flapsClient, appName) if err != nil { return err } diff --git a/internal/command/volumes/fork.go b/internal/command/volumes/fork.go index 970ace75d7..9ffb00a4c2 100644 --- a/internal/command/volumes/fork.go +++ b/internal/command/volumes/fork.go @@ -11,7 +11,6 @@ import ( "github.com/superfly/flyctl/internal/config" "github.com/superfly/flyctl/internal/flag" "github.com/superfly/flyctl/internal/flapsutil" - "github.com/superfly/flyctl/internal/flyutil" "github.com/superfly/flyctl/internal/render" "github.com/superfly/flyctl/iostreams" ) @@ -68,7 +67,6 @@ func runFork(ctx context.Context) error { cfg = config.FromContext(ctx) appName = appconfig.NameFromContext(ctx) volID = flag.FirstArg(ctx) - client = flyutil.ClientFromContext(ctx) ) flapsClient := flapsutil.ClientFromContext(ctx) @@ -78,12 +76,10 @@ func runFork(ctx context.Context) error { err error ) if volID == "" { - var app *fly.AppBasic - app, err = client.GetAppBasic(ctx, appName) - if err != nil { + if _, err = flapsClient.GetApp(ctx, appName); err != nil { return err } - vol, err = selectVolume(ctx, flapsClient, app) + vol, err = selectVolume(ctx, flapsClient, appName) if err != nil { return err } diff --git a/internal/command/volumes/list.go b/internal/command/volumes/list.go index 04d6e24332..ef1613035a 100644 --- a/internal/command/volumes/list.go +++ b/internal/command/volumes/list.go @@ -11,7 +11,6 @@ import ( "github.com/superfly/flyctl/internal/config" "github.com/superfly/flyctl/internal/flag" "github.com/superfly/flyctl/internal/flapsutil" - "github.com/superfly/flyctl/internal/flyutil" "github.com/superfly/flyctl/internal/render" "github.com/superfly/flyctl/iostreams" ) @@ -46,17 +45,16 @@ func newList() *cobra.Command { func runList(ctx context.Context) error { cfg := config.FromContext(ctx) - apiClient := flyutil.ClientFromContext(ctx) appName := appconfig.NameFromContext(ctx) - app, err := apiClient.GetAppBasic(ctx, appName) + flapsClient := flapsutil.ClientFromContext(ctx) + + _, err := flapsClient.GetApp(ctx, appName) if err != nil { return err } - flapsClient := flapsutil.ClientFromContext(ctx) - var volumes []fly.Volume if flag.GetBool(ctx, "all") { volumes, err = flapsClient.GetAllVolumes(ctx, appName) @@ -73,5 +71,5 @@ func runList(ctx context.Context) error { return render.JSON(out, volumes) } - return renderTable(ctx, volumes, app, out, true) + return renderTable(ctx, volumes, out, true) } diff --git a/internal/command/volumes/show.go b/internal/command/volumes/show.go index 0d1f8f9560..8cdb179639 100644 --- a/internal/command/volumes/show.go +++ b/internal/command/volumes/show.go @@ -64,12 +64,10 @@ func runShow(ctx context.Context) error { err error ) if volumeID == "" { - var app *fly.AppBasic - app, err = client.GetAppBasic(ctx, appName) - if err != nil { + if _, err = flapsClient.GetApp(ctx, appName); err != nil { return err } - volume, err = selectVolume(ctx, flapsClient, app) + volume, err = selectVolume(ctx, flapsClient, appName) if err != nil { return err } diff --git a/internal/command/volumes/volumes.go b/internal/command/volumes/volumes.go index ff453b0ced..ee2c6c6c0c 100644 --- a/internal/command/volumes/volumes.go +++ b/internal/command/volumes/volumes.go @@ -90,7 +90,7 @@ func countVolumesMatchingName(ctx context.Context, appName string, volumeName st return matches, nil } -func renderTable(ctx context.Context, volumes []fly.Volume, app *fly.AppBasic, out io.Writer, showHostStatus bool) error { +func renderTable(ctx context.Context, volumes []fly.Volume, out io.Writer, showHostStatus bool) error { rows := make([][]string, 0, len(volumes)) unreachableVolumes := false for _, volume := range volumes { @@ -129,19 +129,19 @@ func renderTable(ctx context.Context, volumes []fly.Volume, app *fly.AppBasic, o return nil } -func selectVolume(ctx context.Context, flapsClient flapsutil.FlapsClient, app *fly.AppBasic) (*fly.Volume, error) { +func selectVolume(ctx context.Context, flapsClient flapsutil.FlapsClient, appName string) (*fly.Volume, error) { if !iostreams.FromContext(ctx).IsInteractive() { return nil, fmt.Errorf("volume ID must be specified when not running interactively") } - volumes, err := flapsClient.GetVolumes(ctx, app.Name) + volumes, err := flapsClient.GetVolumes(ctx, appName) if err != nil { return nil, err } if len(volumes) == 0 { - return nil, fmt.Errorf("no volumes found in app '%s'", app.Name) + return nil, fmt.Errorf("no volumes found in app '%s'", appName) } out := new(bytes.Buffer) - err = renderTable(ctx, volumes, app, out, false) + err = renderTable(ctx, volumes, out, false) if err != nil { return nil, err } diff --git a/internal/flag/completion/completions.go b/internal/flag/completion/completions.go index bfc6829601..7822214eac 100644 --- a/internal/flag/completion/completions.go +++ b/internal/flag/completion/completions.go @@ -9,7 +9,9 @@ import ( "github.com/samber/lo" "github.com/spf13/cobra" fly "github.com/superfly/fly-go" + "github.com/superfly/fly-go/flaps" "github.com/superfly/flyctl/internal/flag/flagnames" + "github.com/superfly/flyctl/internal/flapsutil" "github.com/superfly/flyctl/internal/flyutil" ) @@ -19,41 +21,46 @@ func CompleteApps( args []string, partial string, ) ([]string, error) { - var ( - client = flyutil.ClientFromContext(ctx) + type appInfo struct { + name, orgName, status string + } - apps []fly.App - err error - ) + var apps []appInfo orgFiltered := false // We can't use `flag.*` here because of import cycles. *sigh* orgFlag := cmd.Flag(flagnames.Org) if orgFlag != nil && orgFlag.Changed { - var org *fly.Organization - org, err = client.GetOrganizationBySlug(ctx, orgFlag.Value.String()) + flapsClient := flapsutil.ClientFromContext(ctx) + flapsApps, err := flapsClient.ListApps(ctx, flaps.ListAppsRequest{OrgSlug: orgFlag.Value.String()}) if err != nil { return nil, err } - apps, err = client.GetAppsForOrganization(ctx, org.ID) + for _, app := range flapsApps { + apps = append(apps, appInfo{name: app.Name, orgName: app.Organization.Name, status: app.Status}) + } orgFiltered = true } else { - apps, err = client.GetApps(ctx, nil) - } - if err != nil { - return nil, err + client := flyutil.ClientFromContext(ctx) + gqlApps, err := client.GetApps(ctx, nil) + if err != nil { + return nil, err + } + for _, app := range gqlApps { + apps = append(apps, appInfo{name: app.Name, orgName: app.Organization.Name, status: app.Status}) + } } - ret := lo.FilterMap(apps, func(app fly.App, _ int) (string, bool) { - if strings.HasPrefix(app.Name, partial) { + ret := lo.FilterMap(apps, func(app appInfo, _ int) (string, bool) { + if strings.HasPrefix(app.name, partial) { var info []string if !orgFiltered { - info = append(info, app.Organization.Name) + info = append(info, app.orgName) } - info = append(info, app.Status) + info = append(info, app.status) - return fmt.Sprintf("%s\t%s", app.Name, strings.Join(info, ", ")), true + return fmt.Sprintf("%s\t%s", app.name, strings.Join(info, ", ")), true } return "", false @@ -97,17 +104,23 @@ func CompleteRegions( args []string, partial string, ) ([]string, error) { - client := flyutil.ClientFromContext(ctx) + flapsClient := flapsutil.ClientFromContext(ctx) format := func(org fly.Region) string { return fmt.Sprintf("%s\t%s", org.Code, org.Name) } // TODO(ali): Do we need to worry about which ones are marked as "gateway"? - regions, reqRegion, err := client.PlatformRegions(ctx) + regionData, err := flapsClient.GetRegions(ctx) if err != nil { return nil, err } + regions := regionData.Regions + + var reqRegion *fly.Region + if nearest, ok := lo.Find(regions, func(r fly.Region) bool { return r.Code == regionData.Nearest }); ok { + reqRegion = &nearest + } // Filter out deprecated regions regions = lo.Filter(regions, func(r fly.Region, _ int) bool { diff --git a/internal/flapsutil/app.go b/internal/flapsutil/app.go index afcd56d84c..1c24d161a0 100644 --- a/internal/flapsutil/app.go +++ b/internal/flapsutil/app.go @@ -2,6 +2,14 @@ package flapsutil import "github.com/superfly/fly-go/flaps" +// PostgresAppRole is the app role Flaps reports for Fly Postgres clusters. +const PostgresAppRole = "postgres_cluster" + +// IsPostgresApp reports whether app is a Fly Postgres cluster. +func IsPostgresApp(app *flaps.App) bool { + return app != nil && app.AppRole == PostgresAppRole +} + // DefaultNetwork is the name Flaps reports for an organization's default // network. The web API and WireGuard tunnels identify that network by an // empty name instead. diff --git a/internal/prompt/prompt.go b/internal/prompt/prompt.go index f6a3980bd0..acf44839ab 100644 --- a/internal/prompt/prompt.go +++ b/internal/prompt/prompt.go @@ -18,6 +18,7 @@ import ( fly "github.com/superfly/fly-go" "github.com/superfly/flyctl/internal/config" "github.com/superfly/flyctl/internal/flag" + "github.com/superfly/flyctl/internal/flapsutil" "github.com/superfly/flyctl/internal/flyutil" "github.com/superfly/flyctl/internal/future" "github.com/superfly/flyctl/internal/sort" @@ -324,11 +325,19 @@ var ( func PlatformRegions(ctx context.Context) *future.Future[RegionInfo] { regionsOnce.Do(func() { regionsFuture = future.Spawn(func() (RegionInfo, error) { - client := flyutil.ClientFromContext(ctx) - regions, defaultRegion, err := client.PlatformRegions(ctx) + flapsClient := flapsutil.ClientFromContext(ctx) + regionData, err := flapsClient.GetRegions(ctx) if err != nil { return RegionInfo{}, err } + regions := regionData.Regions + + var defaultRegion *fly.Region + if regionData.Nearest != "" { + if nearest, ok := lo.Find(regions, func(r fly.Region) bool { return r.Code == regionData.Nearest }); ok { + defaultRegion = &nearest + } + } // Filter out deprecated regions regions = lo.Filter(regions, func(r fly.Region, _ int) bool {