diff --git a/auth/creds.go b/auth/creds.go index ee31673fa..b61563871 100644 --- a/auth/creds.go +++ b/auth/creds.go @@ -1,6 +1,6 @@ package auth -// Credentials encapsulates credentials used to encrypt a Vault. +// Credentials encapsulates credentials used to derive master key for repository encryption. type Credentials interface { GetMasterKey(f Options) ([]byte, error) } diff --git a/cli/command_backup.go b/cli/command_backup.go index 4cc46dbd4..bb8040312 100644 --- a/cli/command_backup.go +++ b/cli/command_backup.go @@ -50,7 +50,7 @@ func runBackupCommand(c *kingpin.ParseContext) error { defer conn.Close() ctx := context.Background() - mgr := snapshot.NewManager(conn.Vault) + mgr := snapshot.NewManager(conn) sources := *backupSources if *backupAll { @@ -66,7 +66,7 @@ func runBackupCommand(c *kingpin.ParseContext) error { } for _, backupDirectory := range sources { - conn.Repository.Stats.Reset() + conn.Stats.Reset() log.Printf("Backing up %v", backupDirectory) dir, err := filepath.Abs(backupDirectory) if err != nil { @@ -101,7 +101,7 @@ func runBackupCommand(c *kingpin.ParseContext) error { manifest, err := snapshot.Upload( ctx, - conn.Repository, + conn, localEntry, sourceInfo, policy.Files, diff --git a/cli/command_backups.go b/cli/command_backups.go index aa93057b9..acd62331b 100644 --- a/cli/command_backups.go +++ b/cli/command_backups.go @@ -52,7 +52,7 @@ func runBackupsCommand(context *kingpin.ParseContext) error { conn := mustOpenConnection() defer conn.Close() - mgr := snapshot.NewManager(conn.Vault) + mgr := snapshot.NewManager(conn) var previous []string var relPath string diff --git a/cli/command_cat.go b/cli/command_cat.go index 0e8817450..39b65de9d 100644 --- a/cli/command_cat.go +++ b/cli/command_cat.go @@ -16,11 +16,11 @@ func runCatCommand(context *kingpin.ParseContext) error { conn := mustOpenConnection() defer conn.Close() - oid, err := parseObjectID(*catCommandPath, conn.Vault, conn.Repository) + oid, err := parseObjectID(*catCommandPath, conn) if err != nil { return err } - r, err := conn.Repository.Open(oid) + r, err := conn.Open(oid) if err != nil { return err } diff --git a/cli/command_cleanup.go b/cli/command_cleanup.go index 0771dc132..42729de2f 100644 --- a/cli/command_cleanup.go +++ b/cli/command_cleanup.go @@ -152,7 +152,7 @@ func runCleanupCommand(context *kingpin.ParseContext) error { conn := mustOpenConnection() defer conn.Close() - mgr := snapshot.NewManager(conn.Vault) + mgr := snapshot.NewManager(conn) log.Printf("Listing active snapshots...") snapshotNames, err := mgr.ListSnapshotManifests(nil, -1) @@ -167,7 +167,7 @@ func runCleanupCommand(context *kingpin.ParseContext) error { } ctx := &cleanupContext{ - repo: conn.Repository, + repo: conn, inuse: map[string]bool{}, visited: map[string]bool{}, queue: q, @@ -248,7 +248,7 @@ func runCleanupCommand(context *kingpin.ParseContext) error { var unreferencedBlocks int var unreferencedBytes int64 - blocks, cancel := conn.Repository.Storage.ListBlocks("") + blocks, cancel := conn.Storage.ListBlocks("") defer cancel() for b := range blocks { totalBlocks++ diff --git a/cli/command_expire.go b/cli/command_expire.go index 3aa393af8..a480de4de 100644 --- a/cli/command_expire.go +++ b/cli/command_expire.go @@ -181,7 +181,7 @@ func runExpireCommand(context *kingpin.ParseContext) error { conn := mustOpenConnection() defer conn.Close() - mgr := snapshot.NewManager(conn.Vault) + mgr := snapshot.NewManager(conn) snapshotNames, err := getSnapshotNamesToExpire(mgr) if err != nil { return err diff --git a/cli/command_ls.go b/cli/command_ls.go index 094817af9..4c52bd41d 100644 --- a/cli/command_ls.go +++ b/cli/command_ls.go @@ -5,7 +5,6 @@ "strconv" "strings" - "github.com/kopia/kopia/client" "github.com/kopia/kopia/fs" "github.com/kopia/kopia/fs/repofs" "github.com/kopia/kopia/repo" @@ -26,7 +25,7 @@ func runLSCommand(context *kingpin.ParseContext) error { conn := mustOpenConnection() defer conn.Close() - oid, err := parseObjectID(*lsCommandPath, conn.Vault, conn.Repository) + oid, err := parseObjectID(*lsCommandPath, conn) if err != nil { return err } @@ -46,8 +45,8 @@ func init() { lsCommand.Action(runLSCommand) } -func listDirectory(conn *client.Connection, prefix string, oid repo.ObjectID, indent string) error { - d := repofs.Directory(conn.Repository, oid) +func listDirectory(conn *repo.Repository, prefix string, oid repo.ObjectID, indent string) error { + d := repofs.Directory(conn, oid) entries, err := d.Readdir() if err != nil { diff --git a/cli/command_mount.go b/cli/command_mount.go index ec1a584c8..578d7a441 100644 --- a/cli/command_mount.go +++ b/cli/command_mount.go @@ -43,12 +43,12 @@ func runMountCommand(context *kingpin.ParseContext) error { fuse.VolumeName("Kopia"), ) - oid, err := parseObjectID(*mountObjectID, conn.Vault, conn.Repository) + oid, err := parseObjectID(*mountObjectID, conn) if err != nil { return err } - entry := repofs.Directory(conn.Repository, oid) + entry := repofs.Directory(conn, oid) if *mountTraceFS { entry = loggingfs.Wrap(entry).(fs.Directory) } diff --git a/cli/command_policy_ls.go b/cli/command_policy_ls.go index ca12afd4d..4c90d8ff4 100644 --- a/cli/command_policy_ls.go +++ b/cli/command_policy_ls.go @@ -17,7 +17,7 @@ func init() { func listPolicies(context *kingpin.ParseContext) error { conn := mustOpenConnection() - mgr := snapshot.NewManager(conn.Vault) + mgr := snapshot.NewManager(conn) policies, err := mgr.ListPolicies() if err != nil { diff --git a/cli/command_policy_remove.go b/cli/command_policy_remove.go index a433dc15b..bfa015bc2 100644 --- a/cli/command_policy_remove.go +++ b/cli/command_policy_remove.go @@ -19,7 +19,7 @@ func init() { func removePolicy(context *kingpin.ParseContext) error { conn := mustOpenConnection() - mgr := snapshot.NewManager(conn.Vault) + mgr := snapshot.NewManager(conn) targets, err := policyTargets(policyRemoveGlobal, policyRemoveTargets) if err != nil { diff --git a/cli/command_policy_set.go b/cli/command_policy_set.go index 04aa4226a..ee68f4fdf 100644 --- a/cli/command_policy_set.go +++ b/cli/command_policy_set.go @@ -37,7 +37,7 @@ func init() { func setPolicy(context *kingpin.ParseContext) error { conn := mustOpenConnection() - mgr := snapshot.NewManager(conn.Vault) + mgr := snapshot.NewManager(conn) _ = mgr targets, err := policyTargets(policySetGlobal, policySetTargets) diff --git a/cli/command_policy_show.go b/cli/command_policy_show.go index 0ff9f6fde..a9cbcfc92 100644 --- a/cli/command_policy_show.go +++ b/cli/command_policy_show.go @@ -20,7 +20,7 @@ func init() { func showPolicy(context *kingpin.ParseContext) error { conn := mustOpenConnection() - mgr := snapshot.NewManager(conn.Vault) + mgr := snapshot.NewManager(conn) targets, err := policyTargets(policyShowGlobal, policyShowTargets) if err != nil { diff --git a/cli/command_show.go b/cli/command_show.go index c4e384d98..2ba016630 100644 --- a/cli/command_show.go +++ b/cli/command_show.go @@ -24,12 +24,12 @@ func runShowCommand(context *kingpin.ParseContext) error { defer conn.Close() for _, oidString := range *showObjectIDs { - oid, err := parseObjectID(oidString, conn.Vault, conn.Repository) + oid, err := parseObjectID(oidString, conn) if err != nil { return err } - if err := showObject(conn.Repository, oid); err != nil { + if err := showObject(conn, oid); err != nil { return err } } diff --git a/cli/config.go b/cli/config.go index e56927c33..8ef3b2856 100644 --- a/cli/config.go +++ b/cli/config.go @@ -50,7 +50,7 @@ func getContext() context.Context { return ctx } -func openConnection(options ...repo.RepositoryOption) (*client.Connection, error) { +func openConnection(options ...repo.RepositoryOption) (*repo.Repository, error) { return client.Open(getContext(), vaultConfigFileName(), connectionOptionsFromFlags(options...)) } @@ -75,7 +75,7 @@ func connectionOptionsFromFlags(options ...repo.RepositoryOption) *client.Option return opts } -func mustOpenConnection(repoOptions ...repo.RepositoryOption) *client.Connection { +func mustOpenConnection(repoOptions ...repo.RepositoryOption) *repo.Repository { s, err := openConnection(repoOptions...) failOnError(err) return s @@ -113,8 +113,8 @@ func vaultConfigFileName() string { return filepath.Join(getHomeDir(), ".kopia/vault.config") } -func persistVaultConfig(v *repo.Vault) error { - cfg, err := v.Config() +func persistVaultConfig(r *repo.Vault) error { + cfg, err := r.Config() if err != nil { return err } diff --git a/cli/objref.go b/cli/objref.go index cf941efb8..2c9cdb316 100644 --- a/cli/objref.go +++ b/cli/objref.go @@ -10,7 +10,7 @@ ) // ParseObjectID interprets the given ID string and returns corresponding repo.ObjectID. -func parseObjectID(id string, vlt *repo.Vault, r *repo.Repository) (repo.ObjectID, error) { +func parseObjectID(id string, r *repo.Repository) (repo.ObjectID, error) { head, tail := splitHeadTail(id) if len(head) == 0 { return repo.NullObjectID, fmt.Errorf("invalid object ID: %v", id) diff --git a/client/connection.go b/client/connection.go index 3c2677421..97f01c11e 100644 --- a/client/connection.go +++ b/client/connection.go @@ -18,29 +18,8 @@ _ "github.com/kopia/kopia/blob/gcs" ) -// Connection represents open connection to Vault and Repository. -type Connection struct { - Vault *repo.Vault - Repository *repo.Repository -} - -// Close closes the underlying Vault and Repository. -func (c *Connection) Close() error { - if c.Vault != nil { - c.Vault.Close() - c.Vault = nil - } - - if c.Repository != nil { - c.Repository.Close() - c.Repository = nil - } - - return nil -} - -// Open connects to the Vault and Repository specified in the specified configuration file. -func Open(ctx context.Context, configFile string, options *Options) (*Connection, error) { +// Open connects to the Repository specified in the specified configuration file. +func Open(ctx context.Context, configFile string, options *Options) (*repo.Repository, error) { lc, err := config.LoadFromFile(configFile) if err != nil { return nil, err @@ -71,25 +50,13 @@ func Open(ctx context.Context, configFile string, options *Options) (*Connection vaultStorage = logging.NewWrapper(vaultStorage, logging.Prefix("[VAULT] "), logging.Output(options.TraceStorage)) } - var conn Connection - conn.Vault, err = repo.Open(vaultStorage, creds) + vlt, err := repo.Open(vaultStorage, creds) if err != nil { rawVaultStorage.Close() return nil, fmt.Errorf("unable to open vault: %v", err) } - var repositoryStorage blob.Storage - - if lc.RepoConnection == nil { - repositoryStorage = rawVaultStorage - } else { - repositoryStorage, err = newStorageWithOptions(ctx, *lc.RepoConnection, options) - if err != nil { - vaultStorage.Close() - return nil, err - } - } - + repositoryStorage := rawVaultStorage if options.TraceStorage != nil { repositoryStorage = logging.NewWrapper(repositoryStorage, logging.Prefix("[STORAGE] "), logging.Output(options.TraceStorage)) } @@ -107,14 +74,14 @@ func Open(ctx context.Context, configFile string, options *Options) (*Connection } } - conn.Repository, err = repo.NewRepository(repositoryStorage, conn.Vault.RepoConfig.Format) + r, err := repo.NewRepository(repositoryStorage, vlt.RepoConfig.Format) if err != nil { vaultStorage.Close() repositoryStorage.Close() return nil, err } - - return &conn, nil + r.Vault = vlt + return r, nil } func newStorageWithOptions(ctx context.Context, cfg blob.ConnectionInfo, options *Options) (blob.Storage, error) { diff --git a/internal/config/local_config.go b/internal/config/local_config.go index 4ec83c48c..5fede7726 100644 --- a/internal/config/local_config.go +++ b/internal/config/local_config.go @@ -14,7 +14,7 @@ // LocalConfig is a configuration of Kopia. type LocalConfig struct { - VaultConnection *repo.Config `json:"vault,omitempty"` + VaultConnection *repo.VaultConfig `json:"vault,omitempty"` RepoConnection *blob.ConnectionInfo `json:"repository,omitempty"` // can be nil indicating the same connection as for the vault Caching *caching.Options `json:"caching,omitempty"` } diff --git a/repo/repository.go b/repo/repository.go index 04662634c..bd090276a 100644 --- a/repo/repository.go +++ b/repo/repository.go @@ -7,6 +7,7 @@ // Repository represents storage where both content-addressable and user-addressable data is kept. type Repository struct { *casManager + *Vault Storage blob.Storage } diff --git a/repo/vault.go b/repo/vault.go index 5e9258957..29794fc97 100644 --- a/repo/vault.go +++ b/repo/vault.go @@ -167,20 +167,15 @@ func (v *Vault) List(prefix string, limit int) ([]string, error) { return result, nil } -// Close releases any resources held by Vault and closes repository connection. -func (v *Vault) Close() error { - return v.storage.Close() -} - -// Config represents JSON-compatible configuration of the vault connection, including vault key. -type Config struct { +// VaultConfig represents JSON-compatible configuration of the vault connection, including vault key. +type VaultConfig struct { ConnectionInfo blob.ConnectionInfo `json:"connection"` Key []byte `json:"key,omitempty"` } // Config returns a configuration of vault storage its credentials that's suitable // for storing in configuration file. -func (v *Vault) Config() (*Config, error) { +func (v *Vault) Config() (*VaultConfig, error) { cip, ok := v.storage.(blob.ConnectionInfoProvider) if !ok { return nil, errors.New("repository does not support persisting configuration") @@ -188,7 +183,7 @@ func (v *Vault) Config() (*Config, error) { ci := cip.ConnectionInfo() - return &Config{ + return &VaultConfig{ ConnectionInfo: ci, Key: v.masterKey, }, nil diff --git a/repo/vault_test.go b/repo/vault_test.go index 09e1909fc..9dee4712c 100644 --- a/repo/vault_test.go +++ b/repo/vault_test.go @@ -145,13 +145,6 @@ func verifyVault(t *testing.T, vaultPath string, repoPath string) { assertVaultItems(t, v, "baz", []string{"baz"}) assertVaultItems(t, v, "bazx", nil) } - - if err := v1.Close(); err != nil { - t.Errorf("v1.Close() error: %v", err) - } - if err := v2.Close(); err != nil { - t.Errorf("v2.Close() error: %v", err) - } } func assertVaultItem(t *testing.T, v *Vault, itemID string, expectedData string) { diff --git a/snapshot/manager.go b/snapshot/manager.go index 8c101035b..5b3b3fad9 100644 --- a/snapshot/manager.go +++ b/snapshot/manager.go @@ -26,14 +26,14 @@ // Manager manages filesystem snapshots. type Manager struct { - vault *repo.Vault + repository *repo.Repository snapshotIDSecret []byte policyIDSecret []byte } // ListSources lists all snapshot sources. func (m *Manager) ListSources() ([]*SourceInfo, error) { - names, err := m.vault.List(snapshotPrefix, -1) + names, err := m.repository.List(snapshotPrefix, -1) if err != nil { return nil, err } @@ -64,7 +64,7 @@ func (m *Manager) ListSources() ([]*SourceInfo, error) { // ListSnapshots lists all snapshots for a given source. func (m *Manager) ListSnapshots(si *SourceInfo, limit int) ([]*Manifest, error) { - names, err := m.vault.List(m.snapshotIDPrefix(si), limit) + names, err := m.repository.List(m.snapshotIDPrefix(si), limit) if err != nil { return nil, err } @@ -74,7 +74,7 @@ func (m *Manager) ListSnapshots(si *SourceInfo, limit int) ([]*Manifest, error) // LoadSnapshot loads and parses a snapshot with a given ID. func (m *Manager) LoadSnapshot(manifestID string) (*Manifest, error) { - b, err := m.vault.Get(manifestID) + b, err := m.repository.Get(manifestID) if err != nil { return nil, fmt.Errorf("error loading previous backup: %v", err) } @@ -99,7 +99,7 @@ func (m *Manager) SaveSnapshot(manifest *Manifest) (string, error) { return "", fmt.Errorf("cannot marshal backup manifest to JSON: %v", err) } - if err := m.vault.Put(manifestID, b); err != nil { + if err := m.repository.Put(manifestID, b); err != nil { return "", err } @@ -148,7 +148,7 @@ func (m *Manager) ListSnapshotManifests(src *SourceInfo, limit int) ([]string, e prefix = m.snapshotIDPrefix(src) } - return m.vault.List(prefix, limit) + return m.repository.List(prefix, limit) } // GetEffectivePolicy calculates effective snapshot policy for a given source by combining the source-specifc policy (if any) @@ -229,12 +229,12 @@ func (m *Manager) SavePolicy(p *Policy) error { return fmt.Errorf("cannot marshal policy to JSON: %v", err) } - return m.vault.Put(m.policyID(&p.Source), b) + return m.repository.Put(m.policyID(&p.Source), b) } // RemovePolicy removes the policy for a given source func (m *Manager) RemovePolicy(src *SourceInfo) error { - return m.vault.Remove(m.policyID(src)) + return m.repository.Remove(m.policyID(src)) } // GetPolicy retrieves the Policy for a given source, if defined. @@ -252,7 +252,7 @@ func (m *Manager) policyID(src *SourceInfo) string { } func (m *Manager) getPolicyItem(itemID string) (*Policy, error) { - b, err := m.vault.Get(itemID) + b, err := m.repository.Get(itemID) if err == repo.ErrItemNotFound { return nil, ErrPolicyNotFound } @@ -271,7 +271,7 @@ func (m *Manager) getPolicyItem(itemID string) (*Policy, error) { // ListPolicies returns a list of all policies stored in a vault. func (m *Manager) ListPolicies() ([]*Policy, error) { - names, err := m.vault.List(policyPrefix, -1) + names, err := m.repository.List(policyPrefix, -1) if err != nil { return nil, err } @@ -309,10 +309,10 @@ func (m *Manager) ListPolicies() ([]*Policy, error) { } // NewManager creates new snapshot manager for a given connection. -func NewManager(vlt *repo.Vault) *Manager { +func NewManager(r *repo.Repository) *Manager { return &Manager{ - vlt, - vlt.DeriveKey([]byte("snapshot-id"), 32), - vlt.DeriveKey([]byte("policyID-id"), 32), + r, + r.DeriveKey([]byte("snapshot-id"), 32), + r.DeriveKey([]byte("policyID-id"), 32), } }