diff options
author | James Fargher <jfargher@gitlab.com> | 2023-02-14 02:54:57 +0300 |
---|---|---|
committer | James Fargher <jfargher@gitlab.com> | 2023-02-15 22:20:46 +0300 |
commit | d4cf17fb62e7e7a491cf734200a27a8cc180899d (patch) | |
tree | e0e49db5a35a8e2073616ef63143f206194b0c0e | |
parent | 9b1bb2480275c22dd2157e08a2ec2f7db835657b (diff) |
backup: Use context gitaly servers as fallback when available
This will allow gitaly connection information to be setup globally
instead of sent over stdin in each backup/restore request.
-rw-r--r-- | internal/backup/backup.go | 19 | ||||
-rw-r--r-- | internal/backup/backup_test.go | 34 | ||||
-rw-r--r-- | internal/gitaly/storage/servers.go | 5 |
3 files changed, 58 insertions, 0 deletions
diff --git a/internal/backup/backup.go b/internal/backup/backup.go index fc3ca0ac8..11bb812fb 100644 --- a/internal/backup/backup.go +++ b/internal/backup/backup.go @@ -149,6 +149,10 @@ type CreateRequest struct { // Create creates a repository backup. func (mgr *Manager) Create(ctx context.Context, req *CreateRequest) error { + if err := setContextServerInfo(ctx, &req.Server, req.Repository.GetStorageName()); err != nil { + return fmt.Errorf("manager: %w", err) + } + if isEmpty, err := mgr.isEmpty(ctx, req.Server, req.Repository); err != nil { return fmt.Errorf("manager: %w", err) } else if isEmpty { @@ -196,6 +200,10 @@ type RestoreRequest struct { // Restore restores a repository from a backup. func (mgr *Manager) Restore(ctx context.Context, req *RestoreRequest) error { + if err := setContextServerInfo(ctx, &req.Server, req.Repository.GetStorageName()); err != nil { + return fmt.Errorf("manager: %w", err) + } + if err := mgr.removeRepository(ctx, req.Server, req.Repository); err != nil { return fmt.Errorf("manager: %w", err) } @@ -236,6 +244,17 @@ func (mgr *Manager) Restore(ctx context.Context, req *RestoreRequest) error { return nil } +// setContextServerInfo overwrites server with gitaly connection info from ctx metadata when server is zero. +func setContextServerInfo(ctx context.Context, server *storage.ServerInfo, storageName string) error { + if !server.Zero() { + return nil + } + + var err error + *server, err = storage.ExtractGitalyServer(ctx, storageName) + return err +} + func (mgr *Manager) isEmpty(ctx context.Context, server storage.ServerInfo, repo *gitalypb.Repository) (bool, error) { repoClient, err := mgr.newRepoClient(ctx, server) if err != nil { diff --git a/internal/backup/backup_test.go b/internal/backup/backup_test.go index 753af831e..50f25d93e 100644 --- a/internal/backup/backup_test.go +++ b/internal/backup/backup_test.go @@ -503,6 +503,40 @@ func testManagerRestore(t *testing.T, ctx context.Context) { } } +func TestManager_CreateRestore_contextServerInfo(t *testing.T) { + t.Parallel() + + cfg := testcfg.Build(t) + testcfg.BuildGitalyHooks(t, cfg) + cfg.SocketPath = testserver.RunGitalyServer(t, cfg, nil, setup.RegisterAll) + + ctx := testhelper.Context(t) + + repo, repoPath := gittest.CreateRepository(t, ctx, cfg) + commitID := gittest.WriteCommit(t, cfg, repoPath, gittest.WithBranch("main")) + gittest.WriteTag(t, cfg, repoPath, "v1.0.0", commitID.Revision()) + + backupRoot := testhelper.TempDir(t) + + pool := client.NewPool() + defer testhelper.MustClose(t, pool) + + sink := NewFilesystemSink(backupRoot) + locator, err := ResolveLocator("pointer", sink) + require.NoError(t, err) + + fsBackup := NewManager(sink, locator, pool, "unused-backup-id") + + ctx = testhelper.MergeIncomingMetadata(ctx, testcfg.GitalyServersMetadataFromCfg(t, cfg)) + + require.NoError(t, fsBackup.Create(ctx, &CreateRequest{ + Repository: repo, + })) + require.NoError(t, fsBackup.Restore(ctx, &RestoreRequest{ + Repository: repo, + })) +} + func TestResolveSink(t *testing.T) { ctx := testhelper.Context(t) diff --git a/internal/gitaly/storage/servers.go b/internal/gitaly/storage/servers.go index c9351fc87..f4f2408c5 100644 --- a/internal/gitaly/storage/servers.go +++ b/internal/gitaly/storage/servers.go @@ -19,6 +19,11 @@ type ServerInfo struct { Token string `json:"token"` } +// Zero returns true when no attributes have been set. +func (si ServerInfo) Zero() bool { + return si == ServerInfo{} +} + // GitalyServers hold Gitaly servers info like {"default":{"token":"x","address":"y"}}, // to be passed in `gitaly-servers` metadata. type GitalyServers map[string]ServerInfo |