package azure import ( "context" "errors" "fmt" "net/url" "git.ksdemosapps.com/kylesoda/go-migrate/internal/app/config" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" ) var ( ErrInvalidConnectionString = errors.New("invalid connection string") ErrContainerNotFound = errors.New("container not found") ErrBlobNotFound = errors.New("blob not found") ErrInvalidInput = errors.New("invalid input parameters") ) type Client struct { client *azblob.Client azureStorageConfig config.AzureStorageConfig } func NewClient(azureStorageConfig config.AzureStorageConfig) (*Client, error) { protocol := "https" if !azureStorageConfig.UseHTTPS { protocol = "http" } blobEndpoint, _ := url.JoinPath(azureStorageConfig.ServiceURL, azureStorageConfig.AccountName) connStr := fmt.Sprintf("DefaultEndpointsProtocol=%s;AccountName=%s;AccountKey=%s;BlobEndpoint=%s;", protocol, azureStorageConfig.AccountName, azureStorageConfig.AccountKey, blobEndpoint) client, err := azblob.NewClientFromConnectionString(connStr, nil) if err != nil { return nil, fmt.Errorf("creating azure storage client: %w", err) } return &Client{ client: client, azureStorageConfig: azureStorageConfig, }, nil } func (c *Client) CreateContainer(ctx context.Context, containerName string) error { if containerName == "" { return ErrInvalidInput } _, err := c.client.CreateContainer(ctx, containerName, nil) if err != nil { return fmt.Errorf("creating container %s: %w", containerName, err) } return nil } func (c *Client) UploadBuffer(ctx context.Context, containerName, blobPath string, buffer []byte) error { if containerName == "" || blobPath == "" || buffer == nil { return ErrInvalidInput } _, err := c.client.UploadBuffer(ctx, containerName, blobPath, buffer, nil) if err != nil { return fmt.Errorf("uploading blob %s: %w", blobPath, err) } return nil } func (c *Client) UploadAndGetURL(ctx context.Context, blobPath string, buffer []byte) (string, error) { if blobPath == "" || buffer == nil { return "", ErrInvalidInput } fullPath := blobPath if c.azureStorageConfig.Prefix != "" { fullPath, _ = url.JoinPath(c.azureStorageConfig.Prefix, blobPath) } if err := c.UploadBuffer(ctx, c.azureStorageConfig.Container, fullPath, buffer); err != nil { return "", err } blobEndpoint, _ := url.JoinPath(c.azureStorageConfig.ServiceURL, c.azureStorageConfig.AccountName) blobURL, _ := url.JoinPath(blobEndpoint, c.azureStorageConfig.Container, fullPath) return blobURL, nil }