140 lines
3.3 KiB
Go
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"
|
|
}
|