114 lines
2.9 KiB
Go
114 lines
2.9 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/spf13/afero"
|
|
"github.com/supabase/cli/internal/migration/list"
|
|
"github.com/supabase/cli/internal/utils"
|
|
"github.com/supabase/cli/internal/utils/flags"
|
|
"github.com/supabase/cli/internal/utils/tenant"
|
|
)
|
|
|
|
func Run(ctx context.Context, fsys afero.Fs) error {
|
|
if err := flags.LoadProjectRef(fsys); err != nil && !errors.Is(err, utils.ErrNotLinked) {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
}
|
|
if err := utils.Config.Load("", utils.NewRootFS(fsys)); err != nil && !errors.Is(err, os.ErrNotExist) {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
}
|
|
|
|
serviceImages := CheckVersions(ctx, fsys)
|
|
table := `|SERVICE IMAGE|LOCAL|LINKED|
|
|
|-|-|-|
|
|
`
|
|
for _, image := range serviceImages {
|
|
remote := image.Remote
|
|
if len(remote) == 0 {
|
|
remote = "-"
|
|
}
|
|
table += fmt.Sprintf("|`%s`|`%s`|`%s`|\n", image.Name, image.Local, remote)
|
|
}
|
|
|
|
return list.RenderTable(table)
|
|
}
|
|
|
|
type imageVersion struct {
|
|
Name string `json:"name"`
|
|
Local string `json:"local"`
|
|
Remote string `json:"remote"`
|
|
}
|
|
|
|
func CheckVersions(ctx context.Context, fsys afero.Fs) []imageVersion {
|
|
var remote map[string]string
|
|
if _, err := utils.LoadAccessTokenFS(fsys); err == nil && len(flags.ProjectRef) > 0 {
|
|
remote = listRemoteImages(ctx, flags.ProjectRef)
|
|
}
|
|
var result []imageVersion
|
|
for _, image := range utils.Config.GetServiceImages() {
|
|
parts := strings.Split(image, ":")
|
|
v := imageVersion{Name: parts[0], Local: parts[1]}
|
|
if v.Remote = remote[image]; v.Remote == v.Local {
|
|
delete(remote, image)
|
|
}
|
|
result = append(result, v)
|
|
}
|
|
if len(remote) > 0 {
|
|
fmt.Fprintln(os.Stderr, suggestUpdateCmd(remote))
|
|
}
|
|
return result
|
|
}
|
|
|
|
func listRemoteImages(ctx context.Context, projectRef string) map[string]string {
|
|
linked := make(map[string]string, 4)
|
|
var wg sync.WaitGroup
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
if version, err := tenant.GetDatabaseVersion(ctx, projectRef); err == nil {
|
|
linked[utils.Config.Db.Image] = version
|
|
}
|
|
}()
|
|
keys, err := tenant.GetApiKeys(ctx, projectRef)
|
|
if err != nil {
|
|
wg.Wait()
|
|
return linked
|
|
}
|
|
api := tenant.NewTenantAPI(ctx, projectRef, keys.Anon)
|
|
wg.Add(3)
|
|
go func() {
|
|
defer wg.Done()
|
|
if version, err := api.GetGotrueVersion(ctx); err == nil {
|
|
linked[utils.Config.Auth.Image] = version
|
|
}
|
|
}()
|
|
go func() {
|
|
defer wg.Done()
|
|
if version, err := api.GetPostgrestVersion(ctx); err == nil {
|
|
linked[utils.Config.Api.Image] = version
|
|
}
|
|
}()
|
|
go func() {
|
|
defer wg.Done()
|
|
if version, err := api.GetStorageVersion(ctx); err == nil {
|
|
linked[utils.Config.Storage.Image] = version
|
|
}
|
|
}()
|
|
wg.Wait()
|
|
return linked
|
|
}
|
|
|
|
func suggestUpdateCmd(serviceImages map[string]string) string {
|
|
cmd := fmt.Sprintln(utils.Yellow("WARNING:"), "You are running different service versions locally than your linked project:")
|
|
for k, v := range serviceImages {
|
|
cmd += fmt.Sprintf("%s => %s\n", k, v)
|
|
}
|
|
cmd += fmt.Sprintf("Run %s to update them.", utils.Aqua("supabase link"))
|
|
return cmd
|
|
}
|