2025-03-28 19:57:44 +01:00

140 lines
3.3 KiB
Go

package kopia
import (
"backea/internal/logging"
"context"
"fmt"
"os"
"os/exec"
"strings"
b2_client "backea/internal/client"
)
// KopiaError represents an error in Kopia operations
type KopiaError struct {
Message string
Cause error
}
func (e *KopiaError) Error() string {
if e.Cause != nil {
return e.Message + ": " + e.Cause.Error()
}
return e.Message
}
func (e *KopiaError) Unwrap() error {
return e.Cause
}
func NewKopiaError(message string, cause error) *KopiaError {
return &KopiaError{
Message: message,
Cause: cause,
}
}
// B2Provider implements the Provider interface for Backblaze B2
type B2Provider struct {
logger *logging.Logger
}
// NewB2Provider creates a new B2 provider
func NewB2Provider() *B2Provider {
return &B2Provider{
logger: logging.GetLogger(),
}
}
// Connect connects to a B2 repository
func (p *B2Provider) Connect(ctx context.Context, serviceName string, password string, configPath string) error {
keyID := os.Getenv("B2_KEY_ID")
applicationKey := os.Getenv("B2_APPLICATION_KEY")
if keyID == "" || applicationKey == "" {
return NewKopiaError("B2_KEY_ID and B2_APPLICATION_KEY must be set in .env file", nil)
}
bucketName := p.GetBucketName(serviceName)
B2Client, err := b2_client.NewClientFromEnv()
if err != nil {
return NewKopiaError("failed to initialize B2 client", err)
}
if B2Client == nil {
return NewKopiaError("B2 client not initialized", nil)
}
_, err = B2Client.GetBucket(ctx, bucketName)
if err != nil {
p.logger.Info("Bucket %s not found, creating...", bucketName)
_, err = B2Client.CreateBucket(ctx, bucketName, false)
if err != nil {
return NewKopiaError("failed to create bucket", err)
}
p.logger.Info("Created bucket: %s", bucketName)
}
connectCmd := exec.CommandContext(
ctx,
"kopia",
"--config-file", configPath,
"repository", "connect", "b2",
"--bucket", bucketName,
"--key-id", keyID,
"--key", applicationKey,
"--password", password,
)
err = connectCmd.Run()
if err != nil {
p.logger.Info("Creating new B2 repository for %s", serviceName)
createCmd := exec.CommandContext(
ctx,
"kopia",
"--config-file", configPath,
"repository", "create", "b2",
"--bucket", bucketName,
"--key-id", keyID,
"--key", applicationKey,
"--password", password,
)
createOutput, err := createCmd.CombinedOutput()
if err != nil {
return NewKopiaError(fmt.Sprintf("failed to create repository: %s", string(createOutput)), err)
}
}
return nil
}
// GetRepositoryParams returns parameters for B2 operations
func (p *B2Provider) GetRepositoryParams(serviceName string) ([]string, error) {
keyID := os.Getenv("B2_KEY_ID")
applicationKey := os.Getenv("B2_APPLICATION_KEY")
if keyID == "" || applicationKey == "" {
return nil, NewKopiaError("B2_KEY_ID and B2_APPLICATION_KEY must be set in .env file", nil)
}
bucketName := p.GetBucketName(serviceName)
return []string{
"b2",
"--bucket", bucketName,
"--key-id", keyID,
"--key", applicationKey,
}, nil
}
// GetBucketName returns a bucket name for the service
func (p *B2Provider) GetBucketName(serviceName string) string {
sanitized := strings.ReplaceAll(serviceName, ".", "-")
return fmt.Sprintf("backea-%s", sanitized)
}
// GetProviderType returns the provider type identifier
func (p *B2Provider) GetProviderType() string {
return "b2"
}