44from traitlets import Enum , Unicode , default
55from traitlets .config import Configurable
66import boto3
7+ from tornado .ioloop import PeriodicCallback
78
89# Supported third-party services
910MANAGERS = {}
1011
12+ # 15 minutes
13+ CREDENTIALS_REFRESH = 15 * 60 * 1000
14+
1115# Moved to the architecture of having one provider independent manager.
1216# Keeping the loop in case of future developments that need this feature.
1317for entry in entrypoints .get_group_all ("jupyter_drives.manager_v1" ):
1923class DrivesConfig (Configurable ):
2024 """
2125 Allows configuration of supported drives via jupyter_notebook_config.py
26+ Implements singleton pattern
2227 """
2328
2429 session_token = Unicode (
@@ -48,7 +53,7 @@ class DrivesConfig(Configurable):
4853 allow_none = True ,
4954 help = "Region name." ,
5055 )
51-
56+
5257 api_base_url = Unicode (
5358 config = True ,
5459 help = "Base URL of the provider service REST API." ,
@@ -59,7 +64,7 @@ def set_default_api_base_url(self):
5964 # for AWS S3 drives
6065 if self .provider == "s3" :
6166 return "https://s3.amazonaws.com/" # region? https://s3.<region>.amazonaws.com/
62-
67+
6368 # for Google Cloud Storage drives
6469 elif self .provider == "gcs" :
6570 return "https://www.googleapis.com/"
@@ -71,15 +76,34 @@ def set_default_api_base_url(self):
7176 help = "The source control provider." ,
7277 )
7378
79+ _instance = None
80+
81+ def __new__ (cls , ** kwargs ):
82+ if cls ._instance is None :
83+ cls ._instance = super (DrivesConfig , cls ).__new__ (cls )
84+ cls ._instance ._initialized = False
85+ return cls ._instance
86+
7487 def __init__ (self , ** kwargs ):
88+ if self ._initialized :
89+ return
90+
7591 super ().__init__ (** kwargs )
76- self ._load_credentials ()
77-
78- def _load_credentials (self ):
92+ self ._initialize_credentials_refresh ()
93+ self ._initialized = True
94+
95+ def _initialize_credentials_refresh (self ):
7996 # check if credentials were already set in jupyter_notebook_config.py
8097 if self .access_key_id is not None and self .secret_access_key is not None :
8198 return
82-
99+
100+ self ._load_credentials ()
101+ self ._credential_refresh = PeriodicCallback (
102+ self ._load_credentials , CREDENTIALS_REFRESH
103+ )
104+ self ._credential_refresh .start ()
105+
106+ def _load_credentials (self ):
83107 # automatically extract credentials for S3 drives
84108 try :
85109 s = boto3 .Session ()
@@ -110,4 +134,4 @@ def _load_credentials(self):
110134 self .access_key_id = c .access_key
111135 self .secret_access_key = c .secret_key
112136 self .region_name = s .region_name
113- self .session_token = c .token
137+ self .session_token = c .token
0 commit comments