Skip to content

Commit 70ee325

Browse files
committed
sas url support for blob level
1 parent 1e88c6a commit 70ee325

File tree

1 file changed

+58
-27
lines changed

1 file changed

+58
-27
lines changed

backend/azureblob/azureblob.go

Lines changed: 58 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -541,24 +541,27 @@ type Options struct {
541541

542542
// Fs represents a remote azure server
543543
type Fs struct {
544-
name string // name of this remote
545-
root string // the path we are working on if any
546-
opt Options // parsed config options
547-
ci *fs.ConfigInfo // global config
548-
features *fs.Features // optional features
549-
cntSVCcacheMu sync.Mutex // mutex to protect cntSVCcache
550-
cntSVCcache map[string]*container.Client // reference to containerClient per container
551-
svc *service.Client // client to access azblob
552-
cred azcore.TokenCredential // how to generate tokens (may be nil)
553-
sharedKeyCred *service.SharedKeyCredential // shared key credentials (may be nil)
554-
anonymous bool // if this is anonymous access
555-
rootContainer string // container part of root (if any)
556-
rootDirectory string // directory part of root (if any)
557-
isLimited bool // if limited to one container
558-
cache *bucket.Cache // cache for container creation status
559-
pacer *fs.Pacer // To pace and retry the API calls
560-
uploadToken *pacer.TokenDispenser // control concurrency
561-
publicAccess container.PublicAccessType // Container Public Access Level
544+
name string // name of this remote
545+
root string // the path we are working on if any
546+
opt Options // parsed config options
547+
ci *fs.ConfigInfo // global config
548+
features *fs.Features // optional features
549+
cntSVCcacheMu sync.Mutex // mutex to protect cntSVCcache
550+
cntSVCcache map[string]*container.Client // reference to containerClient per container
551+
svc *service.Client // client to access azblob
552+
containerName string // container Name
553+
blobClient *blob.Client // reference to blob Client
554+
blobBlockClient *blockblob.Client // reference to block blob client
555+
cred azcore.TokenCredential // how to generate tokens (may be nil)
556+
sharedKeyCred *service.SharedKeyCredential // shared key credentials (may be nil)
557+
anonymous bool // if this is anonymous access
558+
rootContainer string // container part of root (if any)
559+
rootDirectory string // directory part of root (if any)
560+
isLimited bool // if limited to one container
561+
cache *bucket.Cache // cache for container creation status
562+
pacer *fs.Pacer // To pace and retry the API calls
563+
uploadToken *pacer.TokenDispenser // control concurrency
564+
publicAccess container.PublicAccessType // Container Public Access Level
562565
}
563566

564567
// Object describes an azure object
@@ -865,8 +868,18 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
865868
}
866869
endpoint := opt.SASURL
867870
containerName := parts.ContainerName
868-
// Check if we have container level SAS or account level SAS
869-
if containerName != "" {
871+
if parts.BlobName != "" {
872+
// Blob level SAS
873+
f.containerName = parts.ContainerName
874+
f.blobClient, err = blob.NewClientWithNoCredential(endpoint, nil)
875+
if err != nil {
876+
return nil, fmt.Errorf("unable to create SAS URL for blob client: %w", err)
877+
}
878+
f.blobBlockClient, err = blockblob.NewClientWithNoCredential(endpoint, nil)
879+
if err != nil {
880+
return nil, fmt.Errorf("unable to create SAS URL for blob block client: %w", err)
881+
}
882+
} else if containerName != "" { // Check if we have container level SAS or account level SAS
870883
// Container level SAS
871884
if f.rootContainer != "" && containerName != f.rootContainer {
872885
return nil, fmt.Errorf("container name in SAS URL (%q) and container provided in command (%q) do not match", containerName, f.rootContainer)
@@ -1106,6 +1119,9 @@ func (f *Fs) newObjectWithInfo(ctx context.Context, remote string, info *contain
11061119
fs: f,
11071120
remote: remote,
11081121
}
1122+
if f.containerName != "" {
1123+
o.remote = f.containerName
1124+
}
11091125
if info != nil {
11101126
err := o.decodeMetaDataFromBlob(info)
11111127
if err != nil {
@@ -1128,12 +1144,20 @@ func (f *Fs) NewObject(ctx context.Context, remote string) (fs.Object, error) {
11281144

11291145
// getBlobSVC creates a blob client
11301146
func (f *Fs) getBlobSVC(container, containerPath string) *blob.Client {
1131-
return f.cntSVC(container).NewBlobClient(containerPath)
1147+
if f.containerName == "" {
1148+
return f.cntSVC(container).NewBlobClient(containerPath)
1149+
} else {
1150+
return f.blobClient
1151+
}
11321152
}
11331153

11341154
// getBlockBlobSVC creates a block blob client
11351155
func (f *Fs) getBlockBlobSVC(container, containerPath string) *blockblob.Client {
1136-
return f.cntSVC(container).NewBlockBlobClient(containerPath)
1156+
if f.containerName == "" {
1157+
return f.cntSVC(container).NewBlockBlobClient(containerPath)
1158+
} else {
1159+
return f.blobBlockClient
1160+
}
11371161
}
11381162

11391163
// updateMetadataWithModTime adds the modTime passed in to o.meta.
@@ -1503,6 +1527,9 @@ func (f *Fs) Put(ctx context.Context, in io.Reader, src fs.ObjectInfo, options .
15031527
fs: f,
15041528
remote: src.Remote(),
15051529
}
1530+
if f.containerName != "" {
1531+
fs.remote = f.containerName
1532+
}
15061533
return fs, fs.Update(ctx, in, src, options...)
15071534
}
15081535

@@ -1949,9 +1976,11 @@ func (f *Fs) copySinglepart(ctx context.Context, remote, dstContainer, dstPath s
19491976
// If it isn't possible then return fs.ErrorCantCopy
19501977
func (f *Fs) Copy(ctx context.Context, src fs.Object, remote string) (fs.Object, error) {
19511978
dstContainer, dstPath := f.split(remote)
1952-
err := f.mkdirParent(ctx, remote)
1953-
if err != nil {
1954-
return nil, err
1979+
if f.containerName == "" {
1980+
err := f.mkdirParent(ctx, remote)
1981+
if err != nil {
1982+
return nil, err
1983+
}
19551984
}
19561985
srcObj, ok := src.(*Object)
19571986
if !ok {
@@ -2881,8 +2910,10 @@ type uploadInfo struct {
28812910
// Prepare the object for upload
28822911
func (o *Object) prepareUpload(ctx context.Context, src fs.ObjectInfo, options []fs.OpenOption) (ui uploadInfo, err error) {
28832912
container, containerPath := o.split()
2884-
if container == "" || containerPath == "" {
2885-
return ui, fmt.Errorf("can't upload to root - need a container")
2913+
if o.fs.containerName == "" {
2914+
if container == "" || containerPath == "" {
2915+
return ui, fmt.Errorf("can't upload to root - need a container")
2916+
}
28862917
}
28872918
// Create parent dir/bucket if not saving directory marker
28882919
metadataMu.Lock()

0 commit comments

Comments
 (0)