outerbounds 0.3.20rc0__py3-none-any.whl → 0.3.21__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
outerbounds/__init__.py CHANGED
@@ -5,16 +5,10 @@ from pathlib import Path
5
5
  import json
6
6
  import os
7
7
  import re
8
- import string
9
8
  import sys
10
9
  import zlib
10
+
11
11
  import click
12
- from kubeconfig import KubeConfig
13
- import yaml
14
- import requests
15
- import base64
16
- import datetime
17
- import hashlib
18
12
 
19
13
 
20
14
  class CheckException(Exception):
@@ -397,282 +391,3 @@ def configure(encoded_config=None, config_dir=None, profile=None, echo=None):
397
391
  except Exception as e:
398
392
  click.secho("Writing the configuration file '{}' failed.".format(writer.path()))
399
393
  click.secho("Error: {}".format(str(e)))
400
-
401
-
402
- def get_k8s_token_response(config_dir, profile):
403
- config_path = path.join(config_dir, "config.json")
404
- if profile != "":
405
- config_path = path.join(config_dir, "config_{}.json".format(profile))
406
- with open(config_path) as json_file:
407
- config = json.load(json_file)
408
- metaflow_token = config["METAFLOW_SERVICE_AUTH_KEY"]
409
-
410
- if config["OBP_AUTH_SERVER"].startswith("https://"):
411
- auth_endpoint = config["OBP_AUTH_SERVER"]
412
- else:
413
- auth_endpoint = "https://{}".format(config["OBP_AUTH_SERVER"])
414
-
415
- if auth_endpoint.endswith("/"):
416
- auth_endpoint = auth_endpoint[:-1]
417
-
418
- generate_token_url = "{}/generate/k8s".format(auth_endpoint)
419
- headers = {"x-api-key": metaflow_token}
420
- response = requests.get(generate_token_url, headers=headers)
421
- if response.status_code == 200:
422
- return json.loads(response.content)
423
- else:
424
- raise Exception(
425
- "Failed to get response. Error: {}".format(response.status_code)
426
- )
427
-
428
-
429
- @cli.command(help="Generate a token to use your cloud workstation")
430
- @click.option(
431
- "-d",
432
- "--config-dir",
433
- default=path.expanduser(os.environ.get("METAFLOW_HOME", "~/.metaflowconfig")),
434
- help="Path to Metaflow configuration directory",
435
- show_default=True,
436
- )
437
- @click.option(
438
- "-p",
439
- "--profile",
440
- default="",
441
- help="The named metaflow profile in which your workstation exists",
442
- )
443
- def generate_workstation_token(config_dir=None, profile=None):
444
- try:
445
- token = get_k8s_token_response(config_dir, profile)["token"]
446
- token_data = base64.b64decode(token.split(".")[1] + "==")
447
- exec_creds = {
448
- "kind": "ExecCredential",
449
- "apiVersion": "client.authentication.k8s.io/v1beta1",
450
- "spec": {},
451
- "status": {
452
- "token": token,
453
- "expirationTimestamp": datetime.datetime.fromtimestamp(
454
- json.loads(token_data)["exp"], datetime.timezone.utc
455
- ).isoformat(),
456
- },
457
- }
458
- click.echo(json.dumps(exec_creds))
459
- except Exception as e:
460
- click.secho("Failed to generate workstation token.", fg="red")
461
- click.secho("Error: {}".format(str(e)))
462
-
463
-
464
- @cli.command(help="Configure a cloud workstation")
465
- @click.option(
466
- "-d",
467
- "--config-dir",
468
- default=path.expanduser(os.environ.get("METAFLOW_HOME", "~/.metaflowconfig")),
469
- help="Path to Metaflow configuration directory",
470
- show_default=True,
471
- )
472
- @click.option(
473
- "-p",
474
- "--profile",
475
- default="",
476
- help="The named metaflow profile in which your workstation exists",
477
- )
478
- def configure_cloud_workstation(config_dir=None, profile=None):
479
- k8s_response = get_k8s_token_response(config_dir, profile)
480
- token_data = base64.b64decode(k8s_response["token"].split(".")[1] + "==")
481
- ws_namespace = "ws-{}".format(
482
- hashlib.md5(bytes(json.loads(token_data)["username"], "utf-8")).hexdigest()
483
- )
484
-
485
- kube_config_path = path.expanduser(os.environ.get("KUBECONFIG", "~/.kube/config"))
486
- kube_config = KubeConfig(kube_config_path)
487
- kube_config.set_context(
488
- "outerbounds-workstations", "outerbounds-cluster", ws_namespace, "obp-user"
489
- )
490
-
491
- kube_config.set_cluster(
492
- "outerbounds-cluster",
493
- server=k8s_response["endpoint"],
494
- insecure_skip_tls_verify=True,
495
- )
496
-
497
- with open(kube_config_path, "r") as f:
498
- kube_yaml = yaml.safe_load(f)
499
-
500
- gen_creds_args = ["generate-workstation-token"]
501
- if profile != "":
502
- gen_creds_args.append("--profile")
503
- gen_creds_args.append(profile)
504
-
505
- gen_creds_args.append("--config-dir")
506
- gen_creds_args.append(config_dir)
507
-
508
- user_exec_creds = {
509
- "exec": {
510
- "apiVersion": "client.authentication.k8s.io/v1beta1",
511
- "command": "outerbounds",
512
- "args": gen_creds_args,
513
- "env": None,
514
- "interactiveMode": "Never",
515
- "provideClusterInfo": False,
516
- }
517
- }
518
-
519
- user_updated = False
520
-
521
- if kube_yaml["users"] is None:
522
- kube_yaml["users"] = []
523
-
524
- for user in kube_yaml["users"]:
525
- if user["name"] == "obp-user":
526
- user["user"] = user_exec_creds
527
- user_updated = True
528
-
529
- if not user_updated:
530
- kube_yaml["users"].append({"name": "obp-user", "user": user_exec_creds})
531
-
532
- with open(kube_config_path, "w") as f:
533
- yaml.safe_dump(kube_yaml, f)
534
-
535
- kube_config.use_context("outerbounds-workstations")
536
-
537
-
538
- def prepare_workstations_api_request(config_dir, profile, api_path):
539
- config_path = path.join(config_dir, "config.json")
540
- if profile != "":
541
- config_path = path.join(config_dir, "config_{}.json".format(profile))
542
- with open(config_path) as json_file:
543
- config = json.load(json_file)
544
- metaflow_token = config["METAFLOW_SERVICE_AUTH_KEY"]
545
-
546
- if config["OBP_AUTH_SERVER"].startswith("https://"):
547
- auth_endpoint = config["OBP_AUTH_SERVER"]
548
- else:
549
- auth_endpoint = "https://{}".format(config["OBP_AUTH_SERVER"])
550
-
551
- if auth_endpoint.endswith("/"):
552
- auth_endpoint = auth_endpoint[:-1]
553
-
554
- api_endpoint = auth_endpoint.replace("auth", "api")
555
- endpoint_url = "{}/{}".format(api_endpoint, api_path)
556
- headers = {"x-api-key": metaflow_token}
557
- return endpoint_url, headers
558
-
559
-
560
- @cli.command(help="List all existing workstations")
561
- @click.option(
562
- "-d",
563
- "--config-dir",
564
- default=path.expanduser(os.environ.get("METAFLOW_HOME", "~/.metaflowconfig")),
565
- help="Path to Metaflow configuration directory",
566
- show_default=True,
567
- )
568
- @click.option(
569
- "-p",
570
- "--profile",
571
- default="",
572
- help="The named metaflow profile in which your workstation exists",
573
- )
574
- def list_workstations(config_dir=None, profile=None):
575
- try:
576
- list_workstations_path = "v1/workstations"
577
- endpoint_url, headers = prepare_workstations_api_request(
578
- config_dir, profile, list_workstations_path
579
- )
580
- response = requests.get(endpoint_url, headers=headers)
581
- if response.status_code == 200:
582
- # Print pretty JSON
583
- click.echo(json.dumps(response.json(), indent=4))
584
- else:
585
- click.secho("Failed to list workstations", fg="red")
586
- click.secho("Error: {}".format(json.dumps(response.json(), indent=4)))
587
- except Exception as e:
588
- click.secho("Failed to list workstations", fg="red")
589
- click.secho("Error: {}".format(str(e)))
590
-
591
-
592
- @cli.command(help="Hibernate workstation")
593
- @click.option(
594
- "-d",
595
- "--config-dir",
596
- default=path.expanduser(os.environ.get("METAFLOW_HOME", "~/.metaflowconfig")),
597
- help="Path to Metaflow configuration directory",
598
- show_default=True,
599
- )
600
- @click.option(
601
- "-p",
602
- "--profile",
603
- default="",
604
- help="The named metaflow profile in which your workstation exists",
605
- )
606
- @click.option(
607
- "-w",
608
- "--workstation",
609
- default="",
610
- help="The ID of the workstation to hibernate",
611
- )
612
- def hibernate_workstation(config_dir=None, profile=None, workstation=None):
613
- if workstation is None or workstation == "":
614
- click.secho("Please specify a workstation ID", fg="red")
615
- return
616
- try:
617
- list_workstations_path = "v1/workstations/hibernate/{}".format(workstation)
618
- endpoint_url, headers = prepare_workstations_api_request(
619
- config_dir, profile, list_workstations_path
620
- )
621
- response = requests.put(endpoint_url, headers=headers)
622
- if response.status_code == 200:
623
- response_json = response.json()
624
- if len(response_json) > 0:
625
- click.echo(json.dumps(response_json, indent=4))
626
- else:
627
- click.secho("Success", fg="green", bold=True)
628
- else:
629
- click.secho("Failed to hibernate workstation", fg="red")
630
- click.secho("Error: {}".format(json.dumps(response.json(), indent=4)))
631
- except Exception as e:
632
- click.secho("Failed to hibernate workstation", fg="red")
633
- click.secho("Error: {}".format(str(e)))
634
-
635
-
636
- @cli.command(help="Restart workstation")
637
- @click.option(
638
- "-d",
639
- "--config-dir",
640
- default=path.expanduser(os.environ.get("METAFLOW_HOME", "~/.metaflowconfig")),
641
- help="Path to Metaflow configuration directory",
642
- show_default=True,
643
- )
644
- @click.option(
645
- "-p",
646
- "--profile",
647
- default="",
648
- help="The named metaflow profile in which your workstation exists",
649
- )
650
- @click.option(
651
- "-w",
652
- "--workstation",
653
- default="",
654
- help="The ID of the workstation to restart",
655
- )
656
- def restart_workstation(config_dir=None, profile=None, workstation=None):
657
- if workstation is None or workstation == "":
658
- click.secho("Please specify a workstation ID", fg="red")
659
- return
660
- try:
661
- list_workstations_path = "v1/workstations/restart/{}".format(workstation)
662
- endpoint_url, headers = prepare_workstations_api_request(
663
- config_dir, profile, list_workstations_path
664
- )
665
- response = requests.put(endpoint_url, headers=headers)
666
- if response.status_code == 200:
667
- # Print pretty JSON
668
- response_json = response.json()
669
- if len(response_json) > 0:
670
- click.echo(json.dumps(response_json, indent=4))
671
- else:
672
- click.secho("Success", fg="green", bold=True)
673
- else:
674
- click.secho("Failed to hibernate workstation", fg="red")
675
- click.secho("Error: {}".format(json.dumps(response.json(), indent=4)))
676
- except Exception as e:
677
- click.secho("Failed to hibernate workstation", fg="red")
678
- click.secho("Error: {}".format(str(e)))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: outerbounds
3
- Version: 0.3.20rc0
3
+ Version: 0.3.21
4
4
  Summary: More Data Science, Less Administration
5
5
  License: Proprietary
6
6
  Keywords: data science,machine learning,MLOps
@@ -13,14 +13,10 @@ Classifier: Programming Language :: Python :: 3.8
13
13
  Classifier: Programming Language :: Python :: 3.9
14
14
  Classifier: Programming Language :: Python :: 3.10
15
15
  Classifier: Programming Language :: Python :: 3.11
16
- Requires-Dist: PyYAML (>=6.0,<7.0)
17
16
  Requires-Dist: click (>=8.1.3,<9.0.0)
18
- Requires-Dist: kubeconfig (>=1.1.1,<2.0.0)
19
- Requires-Dist: ob-metaflow (==2.8.0.1)
20
- Requires-Dist: ob-metaflow-extensions (==1.1.16)
17
+ Requires-Dist: ob-metaflow (==2.8.4.2)
18
+ Requires-Dist: ob-metaflow-extensions (==1.1.19)
21
19
  Requires-Dist: opentelemetry-distro (==0.37b0)
22
20
  Requires-Dist: opentelemetry-exporter-otlp-proto-http (==1.16.0)
23
21
  Requires-Dist: opentelemetry-instrumentation-requests (==0.37b0)
24
- Requires-Dist: types-PyYAML (>=6.0.12.8,<7.0.0.0)
25
- Requires-Dist: types-requests (>=2.28.11.15,<3.0.0.0)
26
22
  Project-URL: Documentation, https://docs.metaflow.org
@@ -0,0 +1,6 @@
1
+ outerbounds/__init__.py,sha256=8DqpohQHW-bb7fMvLEHjnM5DlcLGRw7IthmARDfciKY,13620
2
+ outerbounds/cli_main.py,sha256=k9CgQa-3xvfVcIK_ja2WKsKtwjQma9kYJyQY7LagNe4,56
3
+ outerbounds-0.3.21.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
4
+ outerbounds-0.3.21.dist-info/entry_points.txt,sha256=7ye0281PKlvqxu15rjw60zKg2pMsXI49_A8BmGqIqBw,47
5
+ outerbounds-0.3.21.dist-info/METADATA,sha256=V3Ja9j2HBR2NzsYKOQUsxKSfSBCdB5szScQIzR3knTQ,924
6
+ outerbounds-0.3.21.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- outerbounds/__init__.py,sha256=nbc4Q5XfGhJ5IH6TpQhbRxq4RycpCZdza884KItq0Ak,23393
2
- outerbounds/cli_main.py,sha256=k9CgQa-3xvfVcIK_ja2WKsKtwjQma9kYJyQY7LagNe4,56
3
- outerbounds-0.3.20rc0.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
4
- outerbounds-0.3.20rc0.dist-info/entry_points.txt,sha256=7ye0281PKlvqxu15rjw60zKg2pMsXI49_A8BmGqIqBw,47
5
- outerbounds-0.3.20rc0.dist-info/METADATA,sha256=Jipw5msg0tZxYBUJ5JNpmM5S-C4EarDySSmtgjXt0GA,1109
6
- outerbounds-0.3.20rc0.dist-info/RECORD,,