Skip to content

Commit fd2f913

Browse files
authored
Merge pull request #511 from jkloetzke/fix-505
archive: fix azure backend
2 parents 87e320e + 88ba77a commit fd2f913

File tree

1 file changed

+69
-39
lines changed

1 file changed

+69
-39
lines changed

pym/bob/archive.py

Lines changed: 69 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import gzip
3636
import hashlib
3737
import http.client
38+
import io
3839
import os
3940
import os.path
4041
import signal
@@ -972,19 +973,39 @@ def __exit__(self, exc_type, exc_value, traceback):
972973
return False
973974

974975

976+
class AzureStreamReadAdapter(io.RawIOBase):
977+
def __init__(self, raw):
978+
super().__init__()
979+
self.raw = raw
980+
def readable(self):
981+
return True
982+
def seekable(self):
983+
return False
984+
def writable(self):
985+
return False
986+
def read(self, size = -1):
987+
return self.raw.read(size)
988+
def readall(self):
989+
return self.raw.read()
990+
def readinto(self, buf):
991+
data = self.raw.read(len(buf))
992+
buf[0:len(data)] = data
993+
return len(data)
994+
975995
class AzureArchive(BaseArchive):
976996
def __init__(self, spec):
977997
super().__init__(spec)
978998
self.__container = spec['container']
979999
self.__account = spec['account']
980-
self.__key = spec.get('key')
981-
self.__sasToken = spec.get('sasToken')
1000+
self.__credential = spec.get('key', spec.get('sasToken'))
1001+
1002+
def __getClient(self):
9821003
try:
983-
from azure.storage.blob import BlockBlobService
1004+
from azure.storage.blob import ContainerClient
9841005
except ImportError:
9851006
raise BuildError("azure-storage-blob Python3 library not installed!")
986-
self.__service = BlockBlobService(account_name=self.__account,
987-
account_key=self.__key, sas_token=self.__sasToken, socket_timeout=6000)
1007+
return ContainerClient("https://{}.blob.core.windows.net".format(self.__account),
1008+
self.__container, self.__credential)
9881009

9891010
@staticmethod
9901011
def __makeBlobName(buildId, suffix):
@@ -997,70 +1018,79 @@ def _remoteName(self, buildId, suffix):
9971018
self.__container, self.__makeBlobName(buildId, suffix))
9981019

9991020
def _openDownloadFile(self, buildId, suffix):
1000-
from azure.common import AzureException, AzureMissingResourceHttpError
1001-
(tmpFd, tmpName) = mkstemp()
1021+
client = self.__getClient()
1022+
from azure.core.exceptions import AzureError, ResourceNotFoundError
10021023
try:
1003-
os.close(tmpFd)
1004-
self.__service.get_blob_to_path(self.__container,
1005-
self.__makeBlobName(buildId, suffix), tmpName)
1006-
ret = tmpName
1007-
tmpName = None
1008-
return AzureDownloader(ret)
1009-
except AzureMissingResourceHttpError:
1024+
stream = client.download_blob(self.__makeBlobName(buildId, suffix))
1025+
stream = AzureStreamReadAdapter(stream) # Make io.RawIOBase compatible
1026+
stream = io.BufferedReader(stream, 1048576) # 1MiB buffer. Azure read()s are synchronous.
1027+
ret = AzureDownloader(client, stream)
1028+
client = None
1029+
return ret
1030+
except ResourceNotFoundError:
10101031
raise ArtifactNotFoundError()
1011-
except AzureException as e:
1032+
except AzureError as e:
10121033
raise ArtifactDownloadError(str(e))
10131034
finally:
1014-
if tmpName is not None: os.unlink(tmpName)
1035+
if client is not None: client.close()
10151036

10161037
def _openUploadFile(self, buildId, suffix):
1017-
from azure.common import AzureException
1018-
1038+
containerClient = self.__getClient()
1039+
from azure.core.exceptions import AzureError
10191040
blobName = self.__makeBlobName(buildId, suffix)
1041+
blobClient = None
10201042
try:
1021-
if self.__service.exists(self.__container, blobName):
1043+
blobClient = containerClient.get_blob_client(blobName)
1044+
if blobClient.exists():
10221045
raise ArtifactExistsError()
1023-
except AzureException as e:
1046+
ret = AzureUploader(containerClient, blobClient)
1047+
containerClient = blobClient = None
1048+
return ret
1049+
except AzureError as e:
10241050
raise ArtifactUploadError(str(e))
1025-
(tmpFd, tmpName) = mkstemp()
1026-
os.close(tmpFd)
1027-
return AzureUploader(self.__service, self.__container, tmpName, blobName)
1051+
finally:
1052+
if blobClient is not None: blobClient.close()
1053+
if containerClient is not None: containerClient.close()
10281054

10291055
class AzureDownloader:
1030-
def __init__(self, name):
1031-
self.name = name
1056+
def __init__(self, client, stream):
1057+
self.__client = client
1058+
self.__stream = stream
10321059
def __enter__(self):
1033-
return (self.name, None)
1060+
return (None, self.__stream)
10341061
def __exit__(self, exc_type, exc_value, traceback):
1035-
os.unlink(self.name)
1062+
self.__client.close()
10361063
return False
10371064

10381065
class AzureUploader:
1039-
def __init__(self, service, container, name, remoteName):
1040-
self.__service = service
1041-
self.__container = container
1042-
self.__name = name
1043-
self.__remoteName = remoteName
1066+
def __init__(self, containerClient, blobClient):
1067+
self.__containerClient = containerClient
1068+
self.__blobClient = blobClient
10441069

10451070
def __enter__(self):
1046-
return (self.__name, None)
1071+
self.__tmp = TemporaryFile()
1072+
return (None, self.__tmp)
10471073

10481074
def __exit__(self, exc_type, exc_value, traceback):
10491075
try:
10501076
if exc_type is None:
10511077
self.__upload()
10521078
finally:
1053-
os.unlink(self.__name)
1079+
self.__tmp.close()
1080+
self.__blobClient.close()
1081+
self.__containerClient.close()
10541082
return False
10551083

10561084
def __upload(self):
1057-
from azure.common import AzureException, AzureConflictHttpError
1085+
from azure.core.exceptions import AzureError, ResourceExistsError
10581086
try:
1059-
self.__service.create_blob_from_path(self.__container,
1060-
self.__remoteName, self.__name, if_none_match="*")
1061-
except AzureConflictHttpError:
1087+
self.__tmp.seek(0, os.SEEK_END)
1088+
length = self.__tmp.tell()
1089+
self.__tmp.seek(0)
1090+
self.__blobClient.upload_blob(self.__tmp, length=length, overwrite=False)
1091+
except ResourceExistsError:
10621092
raise ArtifactExistsError()
1063-
except AzureException as e:
1093+
except AzureError as e:
10641094
raise ArtifactUploadError(str(e))
10651095

10661096

0 commit comments

Comments
 (0)