2222 Protocol ,
2323)
2424
25+ from exasol .saas .client .api_access import get_database_id
26+
2527from exasol .bucketfs ._buckets import (
2628 BucketLike ,
2729 MountedBucket ,
2830 SaaSBucket ,
2931)
30- from exasol .bucketfs ._error import BucketFsError
32+ from exasol .bucketfs ._error import (
33+ BucketFsError ,
34+ InferBfsPathError ,
35+ )
3136from exasol .bucketfs ._service import Service
3237
3338ARCHIVE_SUFFIXES = [".tar" , ".gz" , ".tgz" , ".zip" , ".tar" ]
@@ -268,6 +273,14 @@ def __init__(self, path: str | PurePath, bucket_api: BucketLike):
268273 self ._path = PurePath (path )
269274 self ._bucket_api = bucket_api
270275
276+ @property
277+ def bucket_api (self ):
278+ return self ._bucket_api
279+
280+ @property
281+ def path (self ):
282+ return self ._path
283+
271284 def _get_relative_posix (self ) -> str :
272285 """
273286 Returns the pure path of this object as a string, in the format of a bucket
@@ -566,7 +579,6 @@ def build_path(**kwargs) -> PathLike:
566579 Explicitly specified root path in a file system. This is an alternative to
567580 providing the service_name and the bucket_name.
568581 """
569-
570582 backend = kwargs .pop ("backend" , StorageBackend .onprem )
571583 path = kwargs .pop ("path" ) if "path" in kwargs else ""
572584
@@ -578,5 +590,132 @@ def build_path(**kwargs) -> PathLike:
578590 bucket = _create_saas_bucket (** kwargs )
579591 else :
580592 bucket = _create_mounted_bucket (** kwargs )
581-
582593 return BucketPath (path , bucket )
594+
595+
596+ def infer_backend (
597+ bucketfs_host : str | None = None ,
598+ bucketfs_port : int | None = None ,
599+ bucketfs_name : str | None = None ,
600+ bucket : str | None = None ,
601+ bucketfs_user : str | None = None ,
602+ bucketfs_password : str | None = None ,
603+ saas_url : str | None = None ,
604+ saas_account_id : str | None = None ,
605+ saas_database_id : str | None = None ,
606+ saas_database_name : str | None = None ,
607+ saas_token : str | None = None ,
608+ base_path : str | None = None ,
609+ ) -> StorageBackend :
610+ """Infer the backend from the provided parameters: returns 'onprem' or 'saas',
611+ or raises an InferBfsPathError if the list of parameters is insufficient for either of the backends.
612+ """
613+ # On-prem required fields
614+ required_onprem_fields = [
615+ bucketfs_host ,
616+ bucketfs_port ,
617+ bucketfs_name ,
618+ bucket ,
619+ bucketfs_user ,
620+ bucketfs_password ,
621+ ]
622+ # SaaS required fields
623+ required_saas_fields = [saas_url , saas_account_id , saas_token ]
624+ if all (required_onprem_fields ):
625+ return StorageBackend .onprem
626+ elif all (required_saas_fields ) and (saas_database_id or saas_database_name ):
627+ return StorageBackend .saas
628+ elif (bucketfs_name and bucket ) or base_path :
629+ return StorageBackend .mounted
630+ else :
631+ raise InferBfsPathError ("Insufficient parameters to infer backend" )
632+
633+
634+ def get_database_id_by_name (
635+ host : str , account_id : str , pat : str , database_name : str
636+ ) -> str :
637+ database_id = get_database_id (
638+ host = host , account_id = account_id , pat = pat , database_name = database_name
639+ )
640+ if not database_id :
641+ raise InferBfsPathError (f"Could not find database_id for name { database_name } " )
642+ return database_id
643+
644+
645+ def infer_path (
646+ bucketfs_host : str | None = None ,
647+ bucketfs_port : int | None = None ,
648+ bucketfs_name : str | None = None ,
649+ bucket : str | None = None ,
650+ bucketfs_user : str | None = None ,
651+ bucketfs_password : str | None = None ,
652+ bucketfs_use_https : bool = True ,
653+ saas_url : str | None = None ,
654+ saas_account_id : str | None = None ,
655+ saas_database_id : str | None = None ,
656+ saas_database_name : str | None = None ,
657+ saas_token : str | None = None ,
658+ path_in_bucket : str = "" ,
659+ use_ssl_cert_validation : bool = True ,
660+ ssl_trusted_ca : str | None = None ,
661+ base_path : str | None = None ,
662+ ) -> PathLike :
663+ """
664+ Infers the correct storage backend (on-premises BucketFS or SaaS) from the provided parameters
665+ and returns a PathLike object for accessing the specified resource.
666+
667+ Raises:
668+ InferBfsPathError: If the parameters are insufficient or inconsistent and the backend cannot be determined.
669+ """
670+ backend = infer_backend (
671+ bucketfs_host ,
672+ bucketfs_port ,
673+ bucketfs_name ,
674+ bucket ,
675+ bucketfs_user ,
676+ bucketfs_password ,
677+ saas_url ,
678+ saas_account_id ,
679+ saas_database_id ,
680+ saas_database_name ,
681+ saas_token ,
682+ base_path ,
683+ )
684+ if backend == StorageBackend .onprem :
685+ bfs_url = f"{ 'https' if bucketfs_use_https else 'http' } ://{ bucketfs_host } :{ bucketfs_port } "
686+ verify = ssl_trusted_ca or use_ssl_cert_validation
687+ return build_path (
688+ backend = StorageBackend .onprem ,
689+ url = bfs_url ,
690+ username = bucketfs_user ,
691+ password = bucketfs_password ,
692+ service_name = bucketfs_name ,
693+ bucket_name = bucket ,
694+ verify = verify ,
695+ path = path_in_bucket ,
696+ )
697+ elif backend == StorageBackend .saas :
698+ if not saas_database_id and saas_database_name :
699+ saas_database_id = get_database_id_by_name (
700+ host = saas_url ,
701+ account_id = saas_account_id ,
702+ pat = saas_token ,
703+ database_name = saas_database_name ,
704+ )
705+ return build_path (
706+ backend = StorageBackend .saas ,
707+ url = saas_url ,
708+ account_id = saas_account_id ,
709+ database_id = saas_database_id ,
710+ pat = saas_token ,
711+ path = path_in_bucket ,
712+ )
713+ elif backend == StorageBackend .mounted :
714+ return build_path (
715+ backend = StorageBackend .mounted ,
716+ service_name = bucketfs_name ,
717+ bucket_name = bucket ,
718+ base_path = base_path ,
719+ )
720+ else :
721+ raise InferBfsPathError (f"Unsupported backend: { backend } ." )
0 commit comments