114 lines
3.0 KiB
Go

package kopia
import (
"context"
"fmt"
"log"
"os"
"os/exec"
"strings"
b2_client "backea/internal/client"
)
// B2Provider implements the Provider interface for Backblaze B2
type B2Provider struct{}
// NewB2Provider creates a new B2 provider
func NewB2Provider() *B2Provider {
return &B2Provider{}
}
// Connect connects to a B2 repository
func (p *B2Provider) Connect(ctx context.Context, serviceName string, password string, configPath string) error {
// Load environment variables for B2 credentials
keyID := os.Getenv("B2_KEY_ID")
applicationKey := os.Getenv("B2_APPLICATION_KEY")
if keyID == "" || applicationKey == "" {
return fmt.Errorf("B2_KEY_ID and B2_APPLICATION_KEY must be set in .env file")
}
bucketName := p.GetBucketName(serviceName)
// Create B2 client and check if bucket exists, create if not
B2Client, _ := b2_client.NewClientFromEnv()
if B2Client == nil {
return fmt.Errorf("B2 client not initialized")
}
_, err := B2Client.GetBucket(ctx, bucketName)
if err != nil {
log.Printf("Bucket %s not found, creating...", bucketName)
_, err = B2Client.CreateBucket(ctx, bucketName, false)
if err != nil {
return fmt.Errorf("failed to create bucket: %w", err)
}
log.Printf("Created bucket: %s", bucketName)
}
// Try to connect to existing repository with config file
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 {
// Connection failed, create new repository
log.Printf("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 fmt.Errorf("failed to create repository: %w\nOutput: %s", err, createOutput)
}
}
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, fmt.Errorf("B2_KEY_ID and B2_APPLICATION_KEY must be set in .env file")
}
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 {
// Backblaze doesn't allow dots in bucket names
sanitized := strings.ReplaceAll(serviceName, ".", "-")
// Add a prefix to make the bucket name unique
return fmt.Sprintf("backea-%s", sanitized)
}
// GetProviderType returns the provider type identifier
func (p *B2Provider) GetProviderType() string {
return "b2"
}