outerbounds 0.3.55rc4__py3-none-any.whl → 0.3.56__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,12 +1,10 @@
1
1
  import click
2
2
  from . import local_setup_cli
3
3
  from . import workstations_cli
4
- from . import perimeters_cli
5
4
 
6
5
 
7
6
  @click.command(
8
- cls=click.CommandCollection,
9
- sources=[local_setup_cli.cli, workstations_cli.cli, perimeters_cli.cli],
7
+ cls=click.CommandCollection, sources=[local_setup_cli.cli, workstations_cli.cli]
10
8
  )
11
9
  def cli(**kwargs):
12
10
  pass
@@ -586,12 +586,6 @@ class ConfigurationWriter:
586
586
  self.out_dir = out_dir
587
587
  self.profile = profile
588
588
 
589
- ob_config_dir = path.expanduser(os.getenv("OBP_CONFIG_DIR", out_dir))
590
- self.ob_config_path = path.join(
591
- ob_config_dir,
592
- "ob_config_{}.json".format(profile) if profile else "ob_config.json",
593
- )
594
-
595
589
  def decode(self):
596
590
  self.decoded_config = deserialize(self.encoded_config)
597
591
 
@@ -654,16 +648,6 @@ class ConfigurationWriter:
654
648
  with open(config_path, "w") as fd:
655
649
  json.dump(self.existing, fd, indent=4)
656
650
 
657
- # Every time a config is initialized, we should also reset the corresponding ob_config[_profile].json
658
- remote_config = metaflowconfig.init_config(self.out_dir, self.profile)
659
- if "OBP_PERIMETER" in remote_config and "OBP_PERIMETER_URL" in remote_config:
660
- with open(self.ob_config_path, "w") as fd:
661
- ob_config_dict = {
662
- "OB_CURRENT_PERIMETER": remote_config["OBP_PERIMETER"],
663
- "OB_CURRENT_PERIMETER_URL": remote_config["OBP_PERIMETER_URL"],
664
- }
665
- json.dump(ob_config_dict, fd, indent=4)
666
-
667
651
  def confirm_overwrite_config(self, config_path):
668
652
  if os.path.exists(config_path):
669
653
  if not click.confirm(
@@ -110,10 +110,8 @@ def configure_cloud_workstation(config_dir=None, profile=None, binary=None, outp
110
110
  kubeconfig_configure_step = CommandStatus(
111
111
  "ConfigureKubeConfig", OuterboundsCommandStatus.OK, "Kubeconfig is configured"
112
112
  )
113
- try:
114
- if not profile:
115
- profile = metaflowconfig.get_metaflow_profile()
116
113
 
114
+ try:
117
115
  metaflow_token = metaflowconfig.get_metaflow_token_from_config(
118
116
  config_dir, profile
119
117
  )
@@ -196,25 +194,8 @@ def configure_cloud_workstation(config_dir=None, profile=None, binary=None, outp
196
194
  default="",
197
195
  help="The named metaflow profile in which your workstation exists",
198
196
  )
199
- @click.option(
200
- "-o",
201
- "--output",
202
- default="json",
203
- help="Show output in the specified format.",
204
- type=click.Choice(["json"]),
205
- )
206
- def list_workstations(config_dir=None, profile=None, output="json"):
207
- list_response = OuterboundsCommandResponse()
208
- list_step = CommandStatus(
209
- "listWorkstations",
210
- OuterboundsCommandStatus.OK,
211
- "Workstation list successfully fetched!",
212
- )
213
- list_response.add_or_update_data("workstations", [])
214
-
197
+ def list_workstations(config_dir=None, profile=None):
215
198
  try:
216
- if not profile:
217
- profile = metaflowconfig.get_metaflow_profile()
218
199
  metaflow_token = metaflowconfig.get_metaflow_token_from_config(
219
200
  config_dir, profile
220
201
  )
@@ -224,23 +205,17 @@ def list_workstations(config_dir=None, profile=None, output="json"):
224
205
  workstations_response = requests.get(
225
206
  f"{api_url}/v1/workstations", headers={"x-api-key": metaflow_token}
226
207
  )
227
- workstations_response.raise_for_status()
228
- list_response.add_or_update_data(
229
- "workstations", workstations_response.json()["workstations"]
230
- )
231
- if output == "json":
232
- click.echo(json.dumps(list_response.as_dict(), indent=4))
208
+ try:
209
+ workstations_response.raise_for_status()
210
+ click.echo(json.dumps(workstations_response.json(), indent=4))
211
+ except HTTPError:
212
+ click.secho("Failed to generate workstation token.", fg="red")
213
+ click.secho(
214
+ "Error: {}".format(json.dumps(workstations_response.json(), indent=4))
215
+ )
233
216
  except Exception as e:
234
- list_step.update(
235
- OuterboundsCommandStatus.FAIL, "Failed to list workstations", ""
236
- )
237
- list_response.add_step(list_step)
238
- if output == "json":
239
- list_response.add_or_update_data("error", str(e))
240
- click.echo(json.dumps(list_response.as_dict(), indent=4))
241
- else:
242
- click.secho("Failed to list workstations", fg="red", err=True)
243
- click.secho("Error: {}".format(str(e)), fg="red", err=True)
217
+ click.secho("Failed to list workstations", fg="red")
218
+ click.secho("Error: {}".format(str(e)))
244
219
 
245
220
 
246
221
  @cli.command(help="Hibernate workstation", hidden=True)
@@ -268,8 +243,6 @@ def hibernate_workstation(config_dir=None, profile=None, workstation=None):
268
243
  click.secho("Please specify a workstation ID", fg="red")
269
244
  return
270
245
  try:
271
- if not profile:
272
- profile = metaflowconfig.get_metaflow_profile()
273
246
  metaflow_token = metaflowconfig.get_metaflow_token_from_config(
274
247
  config_dir, profile
275
248
  )
@@ -294,7 +267,7 @@ def hibernate_workstation(config_dir=None, profile=None, workstation=None):
294
267
  )
295
268
  except Exception as e:
296
269
  click.secho("Failed to hibernate workstation", fg="red")
297
- click.secho("Error: {}".format(str(e)), fg="red")
270
+ click.secho("Error: {}".format(str(e)))
298
271
 
299
272
 
300
273
  @cli.command(help="Restart workstation to the int", hidden=True)
@@ -322,9 +295,6 @@ def restart_workstation(config_dir=None, profile=None, workstation=None):
322
295
  click.secho("Please specify a workstation ID", fg="red")
323
296
  return
324
297
  try:
325
- if not profile:
326
- profile = metaflowconfig.get_metaflow_profile()
327
-
328
298
  metaflow_token = metaflowconfig.get_metaflow_token_from_config(
329
299
  config_dir, profile
330
300
  )
@@ -349,7 +319,7 @@ def restart_workstation(config_dir=None, profile=None, workstation=None):
349
319
  )
350
320
  except Exception as e:
351
321
  click.secho("Failed to restart workstation", fg="red")
352
- click.secho("Error: {}".format(str(e)), fg="red")
322
+ click.secho("Error: {}".format(str(e)))
353
323
 
354
324
 
355
325
  @cli.command(help="Install dependencies needed by workstations", hidden=True)
@@ -521,63 +491,3 @@ def add_to_path(program_path, platform):
521
491
 
522
492
  def to_windows_path(path):
523
493
  return os.path.normpath(path).replace(os.sep, "\\")
524
-
525
-
526
- @cli.command(help="Show relevant links for a deployment & perimeter", hidden=True)
527
- @click.option(
528
- "-d",
529
- "--config-dir",
530
- default=path.expanduser(os.environ.get("METAFLOW_HOME", "~/.metaflowconfig")),
531
- help="Path to Metaflow configuration directory",
532
- show_default=True,
533
- )
534
- @click.option(
535
- "-p",
536
- "--profile",
537
- default="",
538
- help="The named metaflow profile in which your workstation exists",
539
- )
540
- @click.option(
541
- "--perimeter-id",
542
- default="",
543
- help="The id of the perimeter to use",
544
- )
545
- @click.option(
546
- "-o",
547
- "--output",
548
- default="",
549
- help="Show output in the specified format.",
550
- type=click.Choice(["json", ""]),
551
- )
552
- def show_relevant_links(config_dir=None, profile=None, perimeter_id="", output=""):
553
- show_links_response = OuterboundsCommandResponse()
554
- show_links_step = CommandStatus(
555
- "showRelevantLinks",
556
- OuterboundsCommandStatus.OK,
557
- "Relevant links successfully fetched!",
558
- )
559
- show_links_response.add_or_update_data("links", [])
560
- links = []
561
- try:
562
- metaflow_config = metaflowconfig.init_config(config_dir, profile)
563
- links.append(
564
- {
565
- "id": "metaflow-ui-url",
566
- "url": metaflow_config["METAFLOW_UI_URL"],
567
- "label": "Metaflow UI URL",
568
- }
569
- )
570
- show_links_response.add_or_update_data("links", links)
571
- if output == "json":
572
- click.echo(json.dumps(show_links_response.as_dict(), indent=4))
573
- except Exception as e:
574
- show_links_step.update(
575
- OuterboundsCommandStatus.FAIL, "Failed to show relevant links", ""
576
- )
577
- show_links_response.add_step(show_links_step)
578
- if output == "json":
579
- show_links_response.add_or_update_data("error", str(e))
580
- click.echo(json.dumps(show_links_response.as_dict(), indent=4))
581
- else:
582
- click.secho("Failed to show relevant links", fg="red", err=True)
583
- click.secho("Error: {}".format(str(e)), fg="red", err=True)
@@ -1,13 +1,11 @@
1
1
  import json
2
2
  import os
3
3
  import requests
4
- from os import path
5
- import requests
6
4
 
7
5
 
8
- def init_config(config_dir="", profile="") -> dict:
9
- profile = profile or os.environ.get("METAFLOW_PROFILE")
10
- config_dir = config_dir or os.path.expanduser(
6
+ def init_config() -> dict:
7
+ profile = os.environ.get("METAFLOW_PROFILE")
8
+ config_dir = os.path.expanduser(
11
9
  os.environ.get("METAFLOW_HOME", "~/.metaflowconfig")
12
10
  )
13
11
 
@@ -46,10 +44,13 @@ def get_metaflow_token_from_config(config_dir: str, profile: str) -> str:
46
44
  config_dir (str): Path to the config directory
47
45
  profile (str): The named metaflow profile
48
46
  """
49
- config = init_config(config_dir, profile)
50
- if config is None or "METAFLOW_SERVICE_AUTH_KEY" not in config:
51
- raise Exception("METAFLOW_SERVICE_AUTH_KEY not found in config file")
52
- return config["METAFLOW_SERVICE_AUTH_KEY"]
47
+ config_filename = f"config_{profile}.json" if profile else "config.json"
48
+ config_path = os.path.join(config_dir, config_filename)
49
+ with open(config_path) as json_file:
50
+ config = json.load(json_file)
51
+ if config is None or "METAFLOW_SERVICE_AUTH_KEY" not in config:
52
+ raise Exception("METAFLOW_SERVICE_AUTH_KEY not found in config file")
53
+ return config["METAFLOW_SERVICE_AUTH_KEY"]
53
54
 
54
55
 
55
56
  def get_sanitized_url_from_config(config_dir: str, profile: str, key: str) -> str:
@@ -61,12 +62,16 @@ def get_sanitized_url_from_config(config_dir: str, profile: str, key: str) -> st
61
62
  profile (str): The named metaflow profile
62
63
  key (str): The key to look up in the config file
63
64
  """
64
- config = init_config(config_dir, profile)
65
- if key not in config:
66
- raise Exception(f"Key {key} not found in config")
67
- url_in_config = config[key]
68
- if not url_in_config.startswith("https://"):
69
- url_in_config = f"https://{url_in_config}"
65
+ config_filename = f"config_{profile}.json" if profile else "config.json"
66
+ config_path = os.path.join(config_dir, config_filename)
67
+
68
+ with open(config_path) as json_file:
69
+ config = json.load(json_file)
70
+ if key not in config:
71
+ raise Exception(f"Key {key} not found in config file {config_path}")
72
+ url_in_config = config[key]
73
+ if not url_in_config.startswith("https://"):
74
+ url_in_config = f"https://{url_in_config}"
70
75
 
71
- url_in_config = url_in_config.rstrip("/")
72
- return url_in_config
76
+ url_in_config = url_in_config.rstrip("/")
77
+ return url_in_config
@@ -37,14 +37,10 @@ class OuterboundsCommandResponse:
37
37
  self._message = ""
38
38
  self._steps = []
39
39
  self.metadata = {}
40
- self._data = {}
41
40
 
42
41
  def add_or_update_metadata(self, key, value):
43
42
  self.metadata[key] = value
44
43
 
45
- def add_or_update_data(self, key, value):
46
- self._data[key] = value
47
-
48
44
  def add_step(self, step: CommandStatus):
49
45
  self._steps.append(step)
50
46
  self._process_step_status(step)
@@ -63,11 +59,10 @@ class OuterboundsCommandResponse:
63
59
  self._message = "We found one or more warnings with your installation."
64
60
 
65
61
  def as_dict(self):
66
- self._data["steps"] = [step.as_dict() for step in self._steps]
67
62
  return {
68
63
  "status": self.status.value,
69
64
  "code": self._code,
70
65
  "message": self._message,
66
+ "steps": [step.as_dict() for step in self._steps],
71
67
  "metadata": self.metadata,
72
- "data": self._data,
73
68
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: outerbounds
3
- Version: 0.3.55rc4
3
+ Version: 0.3.56
4
4
  Summary: More Data Science, Less Administration
5
5
  License: Proprietary
6
6
  Keywords: data science,machine learning,MLOps
@@ -23,8 +23,9 @@ Requires-Dist: click (>=8.1.3,<9.0.0)
23
23
  Requires-Dist: google-api-core (>=2.16.1,<3.0.0) ; extra == "gcp"
24
24
  Requires-Dist: google-auth (>=2.27.0,<3.0.0) ; extra == "gcp"
25
25
  Requires-Dist: google-cloud-storage (>=2.14.0,<3.0.0) ; extra == "gcp"
26
- Requires-Dist: ob-metaflow (==2.11.0.4)
27
- Requires-Dist: ob-metaflow-extensions (==1.1.45rc2)
26
+ Requires-Dist: ob-metaflow (==2.11.4.1)
27
+ Requires-Dist: ob-metaflow-extensions (==1.1.46)
28
+ Requires-Dist: ob-metaflow-stubs (==2.11.4.1)
28
29
  Requires-Dist: opentelemetry-distro (==0.41b0)
29
30
  Requires-Dist: opentelemetry-exporter-otlp-proto-http (==1.20.0)
30
31
  Requires-Dist: opentelemetry-instrumentation-requests (==0.41b0)
@@ -0,0 +1,14 @@
1
+ outerbounds/__init__.py,sha256=GPdaubvAYF8pOFWJ3b-sPMKCpyfpteWVMZWkmaYhxRw,32
2
+ outerbounds/cli_main.py,sha256=e9UMnPysmc7gbrimq2I4KfltggyU7pw59Cn9aEguVcU,74
3
+ outerbounds/command_groups/__init__.py,sha256=QPWtj5wDRTINDxVUL7XPqG3HoxHNvYOg08EnuSZB2Hc,21
4
+ outerbounds/command_groups/cli.py,sha256=61VsBlPG2ykP_786eCyllqeM8DMhPAOfj2FhktrSd7k,207
5
+ outerbounds/command_groups/local_setup_cli.py,sha256=g_kkrlDGzYvZTm184pW6QwotpkcqBamB14kH_Kv8TbM,28685
6
+ outerbounds/command_groups/workstations_cli.py,sha256=VgydQzCas3mlAFyzZuanjl1E8Zh7pBrbKbbP6t6N2WU,18237
7
+ outerbounds/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ outerbounds/utils/kubeconfig.py,sha256=l1mUP1j9VIq3fsffi5bJ1Nk-hYlwd1dIqkpj7DvVS1E,7936
9
+ outerbounds/utils/metaflowconfig.py,sha256=6u9D4x-pQVCPKnmGkTg9uSSHrq4mGnWQl7TurwyV2e8,2945
10
+ outerbounds/utils/schema.py,sha256=nBuarFbdZu0LGhG0YkJ6pEIvdglfM_TO_W_Db2vksb0,2017
11
+ outerbounds-0.3.56.dist-info/METADATA,sha256=iYALnqAuZVDKxhiQf02jv_XGCv1NVBnCcHX1MHPn4gw,1407
12
+ outerbounds-0.3.56.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
13
+ outerbounds-0.3.56.dist-info/entry_points.txt,sha256=7ye0281PKlvqxu15rjw60zKg2pMsXI49_A8BmGqIqBw,47
14
+ outerbounds-0.3.56.dist-info/RECORD,,
@@ -1,374 +0,0 @@
1
- import base64
2
- import hashlib
3
- import json
4
- import os
5
- import re
6
- import subprocess
7
- import sys
8
- import zlib
9
- from base64 import b64decode, b64encode
10
- from importlib.machinery import PathFinder
11
- from os import path
12
- from pathlib import Path
13
- from typing import Any, Callable, Dict, List
14
-
15
- import boto3
16
- import click
17
- import requests
18
- from requests.exceptions import HTTPError
19
-
20
- from ..utils import kubeconfig, metaflowconfig
21
- from ..utils.schema import (
22
- CommandStatus,
23
- OuterboundsCommandResponse,
24
- OuterboundsCommandStatus,
25
- )
26
-
27
-
28
- @click.group()
29
- def cli(**kwargs):
30
- pass
31
-
32
-
33
- @cli.command(help="Switch current perimeter", hidden=True)
34
- @click.option(
35
- "-d",
36
- "--config-dir",
37
- default=path.expanduser(os.environ.get("METAFLOW_HOME", "~/.metaflowconfig")),
38
- help="Path to Metaflow configuration directory",
39
- show_default=True,
40
- )
41
- @click.option(
42
- "-p",
43
- "--profile",
44
- default=os.environ.get("METAFLOW_PROFILE", ""),
45
- help="The named metaflow profile in which your workstation exists",
46
- )
47
- @click.option(
48
- "-o",
49
- "--output",
50
- default="",
51
- help="Show output in the specified format.",
52
- type=click.Choice(["json", ""]),
53
- )
54
- @click.option("--id", default="", type=str, help="Perimeter name to switch to")
55
- @click.option(
56
- "-f",
57
- "--force",
58
- is_flag=True,
59
- help="Force change the existing perimeter",
60
- default=False,
61
- )
62
- def switch_perimeter(config_dir=None, profile=None, output="", id=None, force=False):
63
- switch_perimeter_response = OuterboundsCommandResponse()
64
-
65
- switch_perimeter_step = CommandStatus(
66
- "SwitchPerimeter",
67
- OuterboundsCommandStatus.OK,
68
- "Perimeter was successfully switched!",
69
- )
70
-
71
- perimeters = get_perimeters_from_api_or_fail_command(
72
- config_dir, profile, output, switch_perimeter_response, switch_perimeter_step
73
- )
74
- confirm_user_has_access_to_perimeter_or_fail(
75
- id, perimeters, output, switch_perimeter_response, switch_perimeter_step
76
- )
77
-
78
- path_to_config = get_ob_config_file_path(config_dir, profile)
79
-
80
- import fcntl
81
-
82
- try:
83
- if os.path.exists(path_to_config):
84
- if not force:
85
- fd = os.open(path_to_config, os.O_WRONLY)
86
- # Try to acquire an exclusive lock
87
- fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
88
- else:
89
- click.secho(
90
- "Force flag is set. Perimeter will be switched, but can have unintended consequences on other running processes.",
91
- fg="yellow",
92
- err=True,
93
- )
94
-
95
- ob_config_dict = {
96
- "OB_CURRENT_PERIMETER": str(id),
97
- "OB_CURRENT_PERIMETER_URL": perimeters[id]["remote_config_url"],
98
- }
99
-
100
- # Now that we have the lock, we can safely write to the file
101
- with open(path_to_config, "w") as file:
102
- json.dump(ob_config_dict, file, indent=4)
103
-
104
- click.secho("Perimeter switched to {}".format(id), fg="green", err=True)
105
- except BlockingIOError:
106
- # This exception is raised if the file is already locked (non-blocking mode)
107
- # Note that its the metaflow package (the extension actually) that acquires a shared read lock
108
- # on the file whenever a process imports metaflow.
109
- # In the future we might want to get smarter about it and show which process is holding the lock.
110
- click.secho(
111
- "Can't switch perimeter while Metaflow is in use. Please make sure there are no running python processes or notebooks using metaflow.",
112
- fg="red",
113
- err=True,
114
- )
115
- switch_perimeter_step.update(
116
- status=OuterboundsCommandStatus.FAIL,
117
- reason="Can't switch perimeter while Metaflow is in use.",
118
- mitigation="Please make sure there are no running python processes or notebooks using metaflow.",
119
- )
120
-
121
- switch_perimeter_response.add_step(switch_perimeter_step)
122
- if output == "json":
123
- click.echo(json.dumps(switch_perimeter_response.as_dict(), indent=4))
124
- return
125
-
126
-
127
- @cli.command(help="Show current perimeter", hidden=True)
128
- @click.option(
129
- "-d",
130
- "--config-dir",
131
- default=path.expanduser(os.environ.get("METAFLOW_HOME", "~/.metaflowconfig")),
132
- help="Path to Metaflow configuration directory",
133
- show_default=True,
134
- )
135
- @click.option(
136
- "-p",
137
- "--profile",
138
- default=os.environ.get("METAFLOW_PROFILE", ""),
139
- help="Configure a named profile. Activate the profile by setting "
140
- "`METAFLOW_PROFILE` environment variable.",
141
- )
142
- @click.option(
143
- "-o",
144
- "--output",
145
- default="",
146
- help="Show output in the specified format.",
147
- type=click.Choice(["json", ""]),
148
- )
149
- def show_current_perimeter(config_dir=None, profile=None, output=""):
150
- show_current_perimeter_response = OuterboundsCommandResponse()
151
-
152
- show_current_perimeter_step = CommandStatus(
153
- "ShowCurrentPerimeter",
154
- OuterboundsCommandStatus.OK,
155
- "Current Perimeter Fetch Successful.",
156
- )
157
-
158
- ob_config_dict = get_ob_config_or_fail_command(
159
- config_dir,
160
- profile,
161
- output,
162
- show_current_perimeter_response,
163
- show_current_perimeter_step,
164
- )
165
-
166
- perimeters = get_perimeters_from_api_or_fail_command(
167
- config_dir,
168
- profile,
169
- output,
170
- show_current_perimeter_response,
171
- show_current_perimeter_step,
172
- )
173
- confirm_user_has_access_to_perimeter_or_fail(
174
- ob_config_dict["OB_CURRENT_PERIMETER"],
175
- perimeters,
176
- output,
177
- show_current_perimeter_response,
178
- show_current_perimeter_step,
179
- )
180
-
181
- click.secho(
182
- "Current Perimeter: {}".format(ob_config_dict["OB_CURRENT_PERIMETER"]),
183
- fg="green",
184
- err=True,
185
- )
186
-
187
- show_current_perimeter_response.add_or_update_data(
188
- "current_perimeter", ob_config_dict["OB_CURRENT_PERIMETER"]
189
- )
190
-
191
- if output == "json":
192
- click.echo(json.dumps(show_current_perimeter_response.as_dict(), indent=4))
193
-
194
-
195
- @cli.command(help="List all available perimeters", hidden=True)
196
- @click.option(
197
- "-d",
198
- "--config-dir",
199
- default=path.expanduser(os.environ.get("METAFLOW_HOME", "~/.metaflowconfig")),
200
- help="Path to Metaflow configuration directory",
201
- show_default=True,
202
- )
203
- @click.option(
204
- "-p",
205
- "--profile",
206
- default=os.environ.get("METAFLOW_PROFILE", ""),
207
- help="The named metaflow profile in which your workstation exists",
208
- )
209
- @click.option(
210
- "-o",
211
- "--output",
212
- default="",
213
- help="Show output in the specified format.",
214
- type=click.Choice(["json", ""]),
215
- )
216
- def list_perimeters(config_dir=None, profile=None, output=""):
217
- list_perimeters_response = OuterboundsCommandResponse()
218
-
219
- list_perimeters_step = CommandStatus(
220
- "ListPerimeters", OuterboundsCommandStatus.OK, "Perimeter Fetch Successful."
221
- )
222
-
223
- ob_config_dict = get_ob_config_or_fail_command(
224
- config_dir, profile, output, list_perimeters_response, list_perimeters_step
225
- )
226
- active_perimeter = ob_config_dict["OB_CURRENT_PERIMETER"]
227
-
228
- perimeters = get_perimeters_from_api_or_fail_command(
229
- config_dir, profile, output, list_perimeters_response, list_perimeters_step
230
- )
231
-
232
- perimeter_list = []
233
- for perimeter in perimeters.values():
234
- status = "OK"
235
- perimeter_list.append(
236
- {
237
- "id": perimeter["perimeter"],
238
- "active": perimeter["perimeter"] == active_perimeter,
239
- "status": status,
240
- }
241
- )
242
- if perimeter["perimeter"] != active_perimeter:
243
- click.secho("Perimeter: {}".format(perimeter["perimeter"]), err=True)
244
- else:
245
- click.secho(
246
- "Perimeter: {} (active)".format(perimeter["perimeter"]),
247
- fg="green",
248
- err=True,
249
- )
250
-
251
- list_perimeters_response.add_or_update_data("perimeters", perimeter_list)
252
-
253
- if output == "json":
254
- click.echo(json.dumps(list_perimeters_response.as_dict(), indent=4))
255
-
256
-
257
- def get_list_perimeters_api_response(config_dir, profile):
258
- metaflow_token = metaflowconfig.get_metaflow_token_from_config(config_dir, profile)
259
- api_url = metaflowconfig.get_sanitized_url_from_config(
260
- config_dir, profile, "OBP_API_SERVER"
261
- )
262
- perimeters_response = requests.get(
263
- f"{api_url}/v1/me/perimeters?privilege=Execute",
264
- headers={"x-api-key": metaflow_token},
265
- )
266
- perimeters_response.raise_for_status()
267
- return perimeters_response.json()["perimeters"]
268
-
269
-
270
- def get_ob_config_file_path(config_dir: str, profile: str) -> str:
271
- # If OBP_CONFIG_DIR is set, use that, otherwise use METAFLOW_HOME
272
- # If neither are set, use ~/.metaflowconfig
273
- obp_config_dir = path.expanduser(os.environ.get("OBP_CONFIG_DIR", config_dir))
274
-
275
- ob_config_filename = f"ob_config_{profile}.json" if profile else "ob_config.json"
276
- return os.path.expanduser(os.path.join(obp_config_dir, ob_config_filename))
277
-
278
-
279
- def get_perimeters_from_api_or_fail_command(
280
- config_dir: str,
281
- profile: str,
282
- output: str,
283
- command_response: OuterboundsCommandResponse,
284
- command_step: CommandStatus,
285
- ) -> Dict[str, Dict[str, str]]:
286
- try:
287
- perimeters = get_list_perimeters_api_response(config_dir, profile)
288
- except:
289
- click.secho(
290
- "Failed to fetch perimeters from API.",
291
- fg="red",
292
- err=True,
293
- )
294
- command_step.update(
295
- status=OuterboundsCommandStatus.FAIL,
296
- reason="Failed to fetch perimeters from API",
297
- mitigation="",
298
- )
299
- command_response.add_step(command_step)
300
- if output == "json":
301
- click.echo(json.dumps(command_response.as_dict(), indent=4))
302
- sys.exit(1)
303
- return {p["perimeter"]: p for p in perimeters}
304
-
305
-
306
- def get_ob_config_or_fail_command(
307
- config_dir: str,
308
- profile: str,
309
- output: str,
310
- command_response: OuterboundsCommandResponse,
311
- command_step: CommandStatus,
312
- ) -> Dict[str, str]:
313
- path_to_config = get_ob_config_file_path(config_dir, profile)
314
-
315
- if not os.path.exists(path_to_config):
316
- click.secho(
317
- "Config file not found at {}".format(path_to_config), fg="red", err=True
318
- )
319
- command_step.update(
320
- status=OuterboundsCommandStatus.FAIL,
321
- reason="Config file not found",
322
- mitigation="Please make sure the config file exists at {}".format(
323
- path_to_config
324
- ),
325
- )
326
- command_response.add_step(command_step)
327
- if output == "json":
328
- click.echo(json.dumps(command_response.as_dict(), indent=4))
329
- sys.exit(1)
330
-
331
- with open(path_to_config, "r") as file:
332
- ob_config_dict = json.load(file)
333
-
334
- if "OB_CURRENT_PERIMETER" not in ob_config_dict:
335
- click.secho(
336
- "OB_CURRENT_PERIMETER not found in Config file: {}".format(path_to_config),
337
- fg="red",
338
- err=True,
339
- )
340
- command_step.update(
341
- status=OuterboundsCommandStatus.FAIL,
342
- reason="OB_CURRENT_PERIMETER not found in Config file: {}",
343
- mitigation="",
344
- )
345
- command_response.add_step(command_step)
346
- if output == "json":
347
- click.echo(json.dumps(command_response.as_dict(), indent=4))
348
- sys.exit(1)
349
-
350
- return ob_config_dict
351
-
352
-
353
- def confirm_user_has_access_to_perimeter_or_fail(
354
- perimeter_id: str,
355
- perimeters: Dict[str, Any],
356
- output: str,
357
- command_response: OuterboundsCommandResponse,
358
- command_step: CommandStatus,
359
- ):
360
- if perimeter_id not in perimeters:
361
- click.secho(
362
- f"You do not have access to perimeter {perimeter_id} or it does not exist.",
363
- fg="red",
364
- err=True,
365
- )
366
- command_step.update(
367
- status=OuterboundsCommandStatus.FAIL,
368
- reason=f"You do not have access to perimeter {perimeter_id} or it does not exist.",
369
- mitigation="",
370
- )
371
- command_response.add_step(command_step)
372
- if output == "json":
373
- click.echo(json.dumps(command_response.as_dict(), indent=4))
374
- sys.exit(1)
@@ -1,15 +0,0 @@
1
- outerbounds/__init__.py,sha256=GPdaubvAYF8pOFWJ3b-sPMKCpyfpteWVMZWkmaYhxRw,32
2
- outerbounds/cli_main.py,sha256=e9UMnPysmc7gbrimq2I4KfltggyU7pw59Cn9aEguVcU,74
3
- outerbounds/command_groups/__init__.py,sha256=QPWtj5wDRTINDxVUL7XPqG3HoxHNvYOg08EnuSZB2Hc,21
4
- outerbounds/command_groups/cli.py,sha256=H4LxcYTmsY9DQUrReSRLjvbg9s9Ro7s-eUrcMqEJ_9A,261
5
- outerbounds/command_groups/local_setup_cli.py,sha256=0sEi3V0sqoCW0RI2z3xMLNnit0pCsigWQ07m1mhDBso,29524
6
- outerbounds/command_groups/perimeters_cli.py,sha256=9tOql42d00KfHpZYkLLGEAOiy8iRbIzsknldCyICwU0,12063
7
- outerbounds/command_groups/workstations_cli.py,sha256=xHgETjWfUjiIkKODR-4qIS5pSc4ww3VS1ouZM9no8CY,21312
8
- outerbounds/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- outerbounds/utils/kubeconfig.py,sha256=l1mUP1j9VIq3fsffi5bJ1Nk-hYlwd1dIqkpj7DvVS1E,7936
10
- outerbounds/utils/metaflowconfig.py,sha256=HgaDmK3F97rppfGUdysS1Zppe28ERTLV_HcB5IuPpV4,2631
11
- outerbounds/utils/schema.py,sha256=Ht_Yf5uoKO0m36WXHZLSPmWPH6EFWXfZDQsiAUquc5k,2160
12
- outerbounds-0.3.55rc4.dist-info/METADATA,sha256=6dAqYfSf245Yt-UAvKyh3BWE53-cYUbcaQMi9Zphd98,1367
13
- outerbounds-0.3.55rc4.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
14
- outerbounds-0.3.55rc4.dist-info/entry_points.txt,sha256=7ye0281PKlvqxu15rjw60zKg2pMsXI49_A8BmGqIqBw,47
15
- outerbounds-0.3.55rc4.dist-info/RECORD,,