supabase-cli/pkg/config/updater.go

181 lines
6.4 KiB
Go

package config
import (
"context"
"fmt"
"os"
"github.com/go-errors/errors"
v1API "github.com/supabase/cli/pkg/api"
)
type ConfigUpdater struct {
client v1API.ClientWithResponses
}
func NewConfigUpdater(client v1API.ClientWithResponses) ConfigUpdater {
return ConfigUpdater{client: client}
}
func (u *ConfigUpdater) UpdateRemoteConfig(ctx context.Context, remote baseConfig, filter ...func(string) bool) error {
if err := u.UpdateApiConfig(ctx, remote.ProjectId, remote.Api, filter...); err != nil {
return err
}
if err := u.UpdateDbConfig(ctx, remote.ProjectId, remote.Db, filter...); err != nil {
return err
}
if err := u.UpdateAuthConfig(ctx, remote.ProjectId, remote.Auth, filter...); err != nil {
return err
}
if err := u.UpdateStorageConfig(ctx, remote.ProjectId, remote.Storage, filter...); err != nil {
return err
}
if err := u.UpdateExperimentalConfig(ctx, remote.ProjectId, remote.Experimental, filter...); err != nil {
return err
}
return nil
}
func (u *ConfigUpdater) UpdateApiConfig(ctx context.Context, projectRef string, c api, filter ...func(string) bool) error {
apiConfig, err := u.client.V1GetPostgrestServiceConfigWithResponse(ctx, projectRef)
if err != nil {
return errors.Errorf("failed to read API config: %w", err)
} else if apiConfig.JSON200 == nil {
return errors.Errorf("unexpected status %d: %s", apiConfig.StatusCode(), string(apiConfig.Body))
}
apiDiff, err := c.DiffWithRemote(*apiConfig.JSON200)
if err != nil {
return err
} else if len(apiDiff) == 0 {
fmt.Fprintln(os.Stderr, "Remote API config is up to date.")
return nil
}
fmt.Fprintln(os.Stderr, "Updating API service with config:", string(apiDiff))
for _, keep := range filter {
if !keep("api") {
return nil
}
}
if resp, err := u.client.V1UpdatePostgrestServiceConfigWithResponse(ctx, projectRef, c.ToUpdatePostgrestConfigBody()); err != nil {
return errors.Errorf("failed to update API config: %w", err)
} else if resp.JSON200 == nil {
return errors.Errorf("unexpected status %d: %s", resp.StatusCode(), string(resp.Body))
}
return nil
}
func (u *ConfigUpdater) UpdateDbSettingsConfig(ctx context.Context, projectRef string, s settings, filter ...func(string) bool) error {
dbConfig, err := u.client.V1GetPostgresConfigWithResponse(ctx, projectRef)
if err != nil {
return errors.Errorf("failed to read DB config: %w", err)
} else if dbConfig.JSON200 == nil {
return errors.Errorf("unexpected status %d: %s", dbConfig.StatusCode(), string(dbConfig.Body))
}
dbDiff, err := s.DiffWithRemote(*dbConfig.JSON200)
if err != nil {
return err
} else if len(dbDiff) == 0 {
fmt.Fprintln(os.Stderr, "Remote DB config is up to date.")
return nil
}
fmt.Fprintln(os.Stderr, "Updating DB service with config:", string(dbDiff))
for _, keep := range filter {
if !keep("db") {
return nil
}
}
updateBody := s.ToUpdatePostgresConfigBody()
if resp, err := u.client.V1UpdatePostgresConfigWithResponse(ctx, projectRef, updateBody); err != nil {
return errors.Errorf("failed to update DB config: %w", err)
} else if resp.JSON200 == nil {
return errors.Errorf("unexpected status %d: %s", resp.StatusCode(), string(resp.Body))
}
return nil
}
func (u *ConfigUpdater) UpdateDbConfig(ctx context.Context, projectRef string, c db, filter ...func(string) bool) error {
if err := u.UpdateDbSettingsConfig(ctx, projectRef, c.Settings, filter...); err != nil {
return err
}
return nil
}
func (u *ConfigUpdater) UpdateAuthConfig(ctx context.Context, projectRef string, c auth, filter ...func(string) bool) error {
if !c.Enabled {
return nil
}
authConfig, err := u.client.V1GetAuthServiceConfigWithResponse(ctx, projectRef)
if err != nil {
return errors.Errorf("failed to read Auth config: %w", err)
} else if authConfig.JSON200 == nil {
return errors.Errorf("unexpected status %d: %s", authConfig.StatusCode(), string(authConfig.Body))
}
authDiff, err := c.DiffWithRemote(*authConfig.JSON200)
if err != nil {
return err
} else if len(authDiff) == 0 {
fmt.Fprintln(os.Stderr, "Remote Auth config is up to date.")
return nil
}
fmt.Fprintln(os.Stderr, "Updating Auth service with config:", string(authDiff))
for _, keep := range filter {
if !keep("auth") {
return nil
}
}
if resp, err := u.client.V1UpdateAuthServiceConfigWithResponse(ctx, projectRef, c.ToUpdateAuthConfigBody()); err != nil {
return errors.Errorf("failed to update Auth config: %w", err)
} else if status := resp.StatusCode(); status < 200 || status >= 300 {
return errors.Errorf("unexpected status %d: %s", status, string(resp.Body))
}
return nil
}
func (u *ConfigUpdater) UpdateStorageConfig(ctx context.Context, projectRef string, c storage, filter ...func(string) bool) error {
if !c.Enabled {
return nil
}
storageConfig, err := u.client.V1GetStorageConfigWithResponse(ctx, projectRef)
if err != nil {
return errors.Errorf("failed to read Storage config: %w", err)
} else if storageConfig.JSON200 == nil {
return errors.Errorf("unexpected status %d: %s", storageConfig.StatusCode(), string(storageConfig.Body))
}
storageDiff, err := c.DiffWithRemote(*storageConfig.JSON200)
if err != nil {
return err
} else if len(storageDiff) == 0 {
fmt.Fprintln(os.Stderr, "Remote Storage config is up to date.")
return nil
}
fmt.Fprintln(os.Stderr, "Updating Storage service with config:", string(storageDiff))
for _, keep := range filter {
if !keep("storage") {
return nil
}
}
if resp, err := u.client.V1UpdateStorageConfigWithResponse(ctx, projectRef, c.ToUpdateStorageConfigBody()); err != nil {
return errors.Errorf("failed to update Storage config: %w", err)
} else if status := resp.StatusCode(); status < 200 || status >= 300 {
return errors.Errorf("unexpected status %d: %s", status, string(resp.Body))
}
return nil
}
func (u *ConfigUpdater) UpdateExperimentalConfig(ctx context.Context, projectRef string, exp experimental, filter ...func(string) bool) error {
if exp.Webhooks != nil && exp.Webhooks.Enabled {
fmt.Fprintln(os.Stderr, "Enabling webhooks for project:", projectRef)
for _, keep := range filter {
if !keep("webhooks") {
return nil
}
}
if resp, err := u.client.V1EnableDatabaseWebhookWithResponse(ctx, projectRef); err != nil {
return errors.Errorf("failed to enable webhooks: %w", err)
} else if status := resp.StatusCode(); status < 200 || status >= 300 {
return errors.Errorf("unexpected enable webhook status %d: %s", status, string(resp.Body))
}
}
return nil
}