1
1
mirror of https://github.com/cooperspencer/gickup synced 2025-12-30 02:21:40 +01:00
gickup/azureblob/azureblob.go

122 lines
3.5 KiB
Go

package azureblob
import (
"context"
"os"
"path/filepath"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
"github.com/cooperspencer/gickup/logger"
"github.com/cooperspencer/gickup/types"
"github.com/rs/zerolog"
)
var (
sub zerolog.Logger
)
func NewAzureBlobClient(azureblob types.AzureBlob) (*azblob.Client, error) {
sub = logger.CreateSubLogger("stage", "azureblob", "container", azureblob.Container)
if azureblob.UseCliCredential {
// Use Azure CLI Credential
sub.Info().Msg("Using Azure CLI credential")
cred, err := azidentity.NewAzureCLICredential(nil)
if err != nil {
return nil, err
}
client, err := azblob.NewClient(azureblob.Url, cred, nil)
return client, err
}
if azureblob.ClientId != "" && azureblob.ClientSecret != "" && azureblob.TenantId != "" {
// Use Client Secret Credential
sub.Info().Msg("Using Azure Client Secret credential")
cred, err := azidentity.NewClientSecretCredential(azureblob.TenantId, azureblob.ClientId, azureblob.ClientSecret, nil)
if err != nil {
return nil, err
}
client, err := azblob.NewClient(azureblob.Url, cred, nil)
return client, err
}
// Use anonymous credential with SAS URL
sub.Info().Msg("Using no Azure credential (e.g. SAS URL)")
client, err := azblob.NewClientWithNoCredential(azureblob.Url, nil)
return client, err
}
// UploadDirToBlobStorage uploads the contents of a directory to Azure blob storage
func UploadDirToBlobStorage(directory string, blobstorage types.AzureBlob, azureblobclient *azblob.Client) error {
err := filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() || (info.Mode()&os.ModeSymlink != 0) {
return nil // Skip directories and symbolic links
}
// Open the file
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
// Upload the file to blob storage
blobName := filepath.ToSlash(path[len(directory)+1:]) // Blob name in container
_, err = azureblobclient.UploadFile(context.Background(), blobstorage.Container, blobName, file, &azblob.UploadFileOptions{})
if err != nil {
return err
}
return nil
})
if err != nil {
return err
}
return nil
}
// DeleteObjectsNotInRepo deletes objects from the container that are not present in the repository
func DeleteObjectsNotInRepo(directory string, blobdir string, blobstorage types.AzureBlob, azureblobclient *azblob.Client) error {
blobprefix := blobdir + "/"
pager := azureblobclient.NewListBlobsFlatPager(blobstorage.Container, &azblob.ListBlobsFlatOptions{
Prefix: &blobprefix,
Include: azblob.ListBlobsInclude{Snapshots: false, Versions: false},
})
for pager.More() {
page, err := pager.NextPage(context.Background())
if err != nil {
return err
}
for _, blobItem := range page.Segment.BlobItems {
blobName := *blobItem.Name
localPath := filepath.Join(directory, blobName)
if _, err := os.Stat(localPath); err != nil {
if os.IsNotExist(err) {
// File does not exist locally, delete from blob storage
_, err := azureblobclient.DeleteBlob(context.Background(), blobstorage.Container, blobName, &azblob.DeleteBlobOptions{
DeleteSnapshots: to.Ptr(azblob.DeleteSnapshotsOptionTypeInclude),
})
if err != nil {
sub.Error().Err(err).Msgf("Failed to delete blob %s", blobName)
return err
}
sub.Info().Msgf("Deleted blob %s as it does not exist locally", blobName)
}
}
}
}
return nil
}