addftool 0.2.10__py3-none-any.whl → 0.2.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
addftool/addf_portal.py CHANGED
@@ -7,9 +7,28 @@ from addftool.sleep import add_sleep_args, sleep_main
7
7
 
8
8
  from addftool.blob import add_blob_args, blob_main
9
9
 
10
+ # Import version information
11
+ try:
12
+ from importlib.metadata import version
13
+ __version__ = version("addftool")
14
+ except ImportError:
15
+ # Fallback for older Python versions
16
+ import pkg_resources
17
+ __version__ = pkg_resources.get_distribution("addftool").version
18
+ except:
19
+ # Fallback if package is not installed
20
+ __version__ = "0.2.11" # Keep in sync with pyproject.toml
21
+
10
22
 
11
23
  def get_args():
12
24
  parser = argparse.ArgumentParser(description="Addf's tool")
25
+
26
+ # Add version argument
27
+ parser.add_argument(
28
+ '--version', '-v',
29
+ action='version',
30
+ version=f'addftool {__version__}'
31
+ )
13
32
 
14
33
  subparsers = parser.add_subparsers(dest='command', help='Sub-command help')
15
34
  add_killer_args(subparsers)
addftool/blob.py CHANGED
@@ -5,6 +5,8 @@ import json
5
5
  import yaml
6
6
  import tempfile
7
7
  from cryptography.fernet import Fernet
8
+ import yaml
9
+ import datetime
8
10
 
9
11
  from .util import execute_command
10
12
 
@@ -231,6 +233,128 @@ def get_sas_token_for_blob_url(api_url, blob_url, key, info=False):
231
233
  return get_sas_token(api_url, an, cn, key, info=info)
232
234
 
233
235
 
236
+ def parse_sas_token_from_blobfuse_config(config_file):
237
+ sas_token = None
238
+ account_name = None
239
+ container_name = None
240
+ with open(config_file, 'r') as f:
241
+ try:
242
+ config = yaml.safe_load(f)
243
+ if 'sas' in config["azstorage"] and config["azstorage"]['mode'] == 'sas':
244
+ sas_token = config['azstorage']['sas']
245
+ if 'account-name' in config["azstorage"]:
246
+ account_name = config['azstorage']['account-name']
247
+ if 'container' in config["azstorage"]:
248
+ container_name = config['azstorage']['container']
249
+ else:
250
+ print(f"No 'sas' found in config file: {config_file}")
251
+ except yaml.YAMLError as exc:
252
+ print(exc)
253
+
254
+ if sas_token is None:
255
+ return None, None, None
256
+
257
+ # parse expiry time from sas token
258
+ expiry_time = None
259
+ try:
260
+ sas_parts = sas_token.split('&')
261
+ for part in sas_parts:
262
+ if part.startswith('se='):
263
+ expiry_time = part[3:]
264
+ break
265
+ except Exception as e:
266
+ print(f"Error parsing expiry time from sas token: {e}")
267
+
268
+ # Expiry Time: 2025-10-28T05%3A22Z, convert into timestamp
269
+ if expiry_time is not None:
270
+ try:
271
+ expiry_time = datetime.datetime.strptime(expiry_time, "%Y-%m-%dT%H%%3A%MZ")
272
+ except Exception as e:
273
+ print(f"Error converting expiry time to timestamp: {e}")
274
+
275
+ blob_url = f"https://{account_name}.blob.core.windows.net/{container_name}"
276
+ return sas_token, blob_url, expiry_time
277
+
278
+
279
+ def update_blobfuse2_yaml_sas_token(config_file, new_sas_token):
280
+ with open(config_file, 'r') as f:
281
+ try:
282
+ config = yaml.safe_load(f)
283
+ except yaml.YAMLError as exc:
284
+ print(exc)
285
+ return False
286
+
287
+ config['azstorage']['sas'] = new_sas_token
288
+
289
+ with open(config_file, 'w') as f:
290
+ try:
291
+ yaml.dump(config, f)
292
+ return True
293
+ except yaml.YAMLError as exc:
294
+ print(exc)
295
+ return False
296
+
297
+
298
+ def update_blobfuse2_config(config_file, api_url, key, hour_threshold=48, view=False):
299
+ is_success = False
300
+ try:
301
+ sas_token, blob_url, expiry_time = parse_sas_token_from_blobfuse_config(config_file)
302
+ if view and blob_url is not None:
303
+ print(f"{blob_url} expiry time: {expiry_time}")
304
+ return False
305
+ if expiry_time is not None:
306
+ now = datetime.datetime.now()
307
+ time_left = expiry_time - now if expiry_time is not None else None
308
+ if time_left is not None and time_left.total_seconds() < 3600 * hour_threshold:
309
+ updated_sas_token = get_sas_token_for_blob_url(api_url, blob_url, key)
310
+ if updated_sas_token:
311
+ is_success = update_blobfuse2_yaml_sas_token(config_file, updated_sas_token)
312
+ except Exception as e:
313
+ print(f"Error updating blobfuse2 config: {e}")
314
+ return False
315
+ return is_success
316
+
317
+
318
+ def refresh_all_blobfuse2_configs(api_url, key, hour_threshold=48, view=False, selected_mount_paths=None):
319
+ from addftool.process.utils import get_processes
320
+ if not view:
321
+ assert api_url is not None and key is not None, "api url and key must be provided when not in view mode"
322
+ procs = get_processes(command="blobfuse2", contains=False)
323
+ for proc in procs:
324
+ config_file = None
325
+ for arg in proc['command'][1:]:
326
+ if arg.startswith("--config-file="):
327
+ config_file = arg.split("=", 1)[1]
328
+ break
329
+ if selected_mount_paths is not None and config_file is not None:
330
+ mount_path = proc['command'][2]
331
+ # print(f"mount_path: {mount_path}, selected_mount_paths: {selected_mount_paths}")
332
+ if mount_path not in selected_mount_paths:
333
+ continue
334
+ if config_file is not None:
335
+ state = update_blobfuse2_config(config_file, api_url, key, hour_threshold=hour_threshold, view=view)
336
+ if state:
337
+ print(f"Updated SAS token in config file for {' '.join(proc['command'])}")
338
+
339
+
340
+ def refresh_main(args):
341
+ # only update current user's blobfuse2 configs
342
+ selected_mount_paths = []
343
+ # df -h | grep blobfuse2
344
+ current_user_file_systems = os.popen("df -h | grep blobfuse2").readlines()
345
+ for line in current_user_file_systems:
346
+ parts = line.split()
347
+ if len(parts) >= 6:
348
+ mount_path = parts[5]
349
+ selected_mount_paths.append(mount_path)
350
+
351
+ print(f"selected_mount_paths for current user: {selected_mount_paths}")
352
+ refresh_all_blobfuse2_configs(
353
+ args.api, args.key, hour_threshold=args.hour_threshold,
354
+ view=args.view, selected_mount_paths=selected_mount_paths,
355
+ )
356
+
357
+
234
358
  def add_args(parser):
235
359
  subparsers = parser.add_subparsers(dest='blob_command', help='Sub-command help')
236
360
  install_parser = subparsers.add_parser('install', help='Install help')
@@ -251,6 +375,12 @@ def add_args(parser):
251
375
  token_parser = subparsers.add_parser('token', help='Token help')
252
376
  add_api(token_parser)
253
377
 
378
+ refresh_parser = subparsers.add_parser('refresh', help='Refresh help')
379
+ refresh_parser.add_argument("-k", "--key", help="f key", type=str)
380
+ refresh_parser.add_argument("-a", "--api", help="api url", type=str)
381
+ refresh_parser.add_argument("-v", "--view", help="view token info", action="store_true")
382
+ refresh_parser.add_argument("-s", "--hour_threshold", help="hour threshold", type=int, default=48)
383
+
254
384
  def add_blob_args(subparsers):
255
385
  deploy_parser = subparsers.add_parser('blob', help='Blob help')
256
386
  add_args(deploy_parser)
@@ -267,6 +397,8 @@ def blob_main(args):
267
397
  mount_main(args)
268
398
  elif args.blob_command == 'token':
269
399
  print(get_token(args, info=False))
400
+ elif args.blob_command == 'refresh':
401
+ refresh_main(args)
270
402
 
271
403
 
272
404
  def main():
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: addftool
3
- Version: 0.2.10
3
+ Version: 0.2.13
4
4
  Requires-Dist: cryptography
5
5
  Requires-Dist: requests
6
6
  Requires-Dist: PyYAML
@@ -8,4 +8,3 @@ Requires-Dist: psutil
8
8
  Requires-Dist: fabric
9
9
  Requires-Dist: gevent
10
10
  Requires-Dist: parallel-ssh
11
-
@@ -1,6 +1,6 @@
1
1
  addftool/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- addftool/addf_portal.py,sha256=vc8opPzValNFPwJne5C5LbZvgcJ0eMBJSWDSiM23OPM,1274
3
- addftool/blob.py,sha256=vyjJHlQZuGrpEiaRF-Bdmow_TMnhXtXEGL31qA5Hb-g,9742
2
+ addftool/addf_portal.py,sha256=CnOAq3JLQjK9-OyYWDYcmtLBM68L3N6WeP5NjBod4zc,1819
3
+ addftool/blob.py,sha256=prGpDy_esyBL53a5R3yVJdGiXQSPFuU4is1yM9dp2qo,15037
4
4
  addftool/broadcast_folder.py,sha256=GQBuSL8Ch537V_fSBHesWyqT3KRYry68pbYOKy2bDj4,19619
5
5
  addftool/sleep.py,sha256=kykcZR2tA0ZpRUwQf6IIUdJ4dYkolyD91FdriViq9Nc,11771
6
6
  addftool/sync.py,sha256=ZpYxbM8uiPFrV7ODmOaM7asVPCWaxBixA-arVc-1kfs,14045
@@ -13,8 +13,8 @@ addftool/deploy/vscode_server.py,sha256=tLtSvlcK2fEOaw6udWt8dNELVhwv9F59hF5DJJ-1
13
13
  addftool/process/__init__.py,sha256=Dze8OrcyjQlAbPrjE_h8bMi8W4b3OJyZOjTucPrkJvM,3721
14
14
  addftool/process/utils.py,sha256=JldxnwanLJOgxaPgmCJh7SeBRaaj5rFxWWxh1hpsvbA,2609
15
15
  addftool/ssh/__init__.py,sha256=h5_rCO0A6q2Yw9vFguQZZp_ApAJsT1dcnKnbKKZ0cDM,4409
16
- addftool-0.2.10.dist-info/METADATA,sha256=01FZkhGtA7aa_vx22DMHcoFcuN6rPagl6Y0xYMKkd9o,222
17
- addftool-0.2.10.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
18
- addftool-0.2.10.dist-info/entry_points.txt,sha256=9lkmuWMInwUAtev8w8poNkNd7iML9Bjd5CBCFVxg2b8,111
19
- addftool-0.2.10.dist-info/top_level.txt,sha256=jqj56-plrBbyzY0tIxB6wPzjAA8kte4hUlajyyQygN4,9
20
- addftool-0.2.10.dist-info/RECORD,,
16
+ addftool-0.2.13.dist-info/METADATA,sha256=C8_l-dQvZoQ8gkxbP86PYJsfAHzjNiMhBW5lCtq8rCI,221
17
+ addftool-0.2.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
+ addftool-0.2.13.dist-info/entry_points.txt,sha256=9lkmuWMInwUAtev8w8poNkNd7iML9Bjd5CBCFVxg2b8,111
19
+ addftool-0.2.13.dist-info/top_level.txt,sha256=jqj56-plrBbyzY0tIxB6wPzjAA8kte4hUlajyyQygN4,9
20
+ addftool-0.2.13.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.2)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5