|
1 | 1 | import io |
| 2 | +import pathlib |
2 | 3 | from britive.britive import Britive |
3 | 4 | from .helpers.config import ConfigManager |
4 | 5 | from .helpers.credentials import FileCredentialManager, EncryptedFileCredentialManager |
|
15 | 16 | from datetime import datetime |
16 | 17 | import os |
17 | 18 | import sys |
| 19 | +import jmespath |
18 | 20 |
|
19 | 21 |
|
20 | 22 | default_table_format = 'fancy_grid' |
@@ -142,9 +144,17 @@ def print(self, data: object, ignore_silent: bool = False): |
142 | 144 |
|
143 | 145 | if self.output_format == 'json': |
144 | 146 | click.echo(json.dumps(data, indent=2, default=str)) |
145 | | - elif self.output_format == 'list': |
| 147 | + elif self.output_format == 'list-profiles': |
146 | 148 | for row in data: |
147 | 149 | click.echo(self.list_separator.join([self.escape_profile_element(x) for x in row.values()])) |
| 150 | + elif self.output_format == 'list': |
| 151 | + for row in data: |
| 152 | + if isinstance(row, dict): |
| 153 | + click.echo(self.list_separator.join([json.dumps(x, default=str) for x in row.values()])) |
| 154 | + elif isinstance(row, list): |
| 155 | + click.echo(self.list_separator.join([json.dumps(x, default=str) for x in row])) |
| 156 | + else: |
| 157 | + click.echo(row) |
148 | 158 | elif self.output_format == 'csv': |
149 | 159 | fields = list(data[0].keys()) |
150 | 160 | output = io.StringIO() |
@@ -202,8 +212,18 @@ def list_profiles(self, checked_out: bool = False): |
202 | 212 | row.pop('Description') |
203 | 213 | row.pop('Type') |
204 | 214 | data.append(row) |
| 215 | + |
| 216 | + # set special list output if needed |
| 217 | + if self.output_format == 'list': |
| 218 | + self.output_format = 'list-profiles' |
| 219 | + |
205 | 220 | self.print(data) |
206 | 221 |
|
| 222 | + # and set it back |
| 223 | + if self.output_format == 'list-profiles': |
| 224 | + self.output_format = 'list' |
| 225 | + |
| 226 | + |
207 | 227 | def list_applications(self): |
208 | 228 | self.login() |
209 | 229 | self._set_available_profiles() |
@@ -596,6 +616,61 @@ def request_withdraw(self, profile): |
596 | 616 | def clear_gcloud_auth_key_files(self): |
597 | 617 | self.config.clear_gcloud_auth_key_files() |
598 | 618 |
|
| 619 | + def api(self, method, parameters={}, query=None): |
| 620 | + self.login() |
| 621 | + |
| 622 | + # clean up parameters - need to load json as dict if json string is provided and handle file inputs |
| 623 | + computed_parameters = {} |
| 624 | + open_file_keys = [] |
| 625 | + for key, value in parameters.items(): |
| 626 | + computed_key = key.replace('-', '_') |
| 627 | + computed_value = value |
| 628 | + |
| 629 | + if value.lower() == 'none': |
| 630 | + computed_value = None |
| 631 | + |
| 632 | + if value.startswith('file://'): |
| 633 | + filepath = value.replace('file://', '') |
| 634 | + path = pathlib.Path(filepath) |
| 635 | + with open(str(path), 'r') as f: |
| 636 | + computed_value = f.read().strip() |
| 637 | + |
| 638 | + if value.startswith('fileb://'): |
| 639 | + filepath = value.replace('fileb://', '') |
| 640 | + path = pathlib.Path(filepath) |
| 641 | + computed_value = open(str(path), 'rb') |
| 642 | + open_file_keys.append(computed_key) |
| 643 | + |
| 644 | + try: |
| 645 | + computed_parameters[computed_key] = json.loads(computed_value) |
| 646 | + except json.JSONDecodeError: |
| 647 | + computed_parameters[computed_key] = computed_value |
| 648 | + except Exception: # not sure what else we would do so just default to the value provided |
| 649 | + computed_parameters[computed_key] = computed_value |
| 650 | + |
| 651 | + # determine the sdk method we need to execute, starting at the base Britive class |
| 652 | + func = self.b |
| 653 | + try: |
| 654 | + for m in method.split('.'): |
| 655 | + func = getattr(func, m) |
| 656 | + except Exception as e: |
| 657 | + raise click.ClickException(f'invalid method {method} provided.') |
| 658 | + |
| 659 | + # execute the method with the computed parameters |
| 660 | + response = func(**computed_parameters) |
| 661 | + |
| 662 | + # close any files we opened due to fileb:// prefix |
| 663 | + for key in open_file_keys: |
| 664 | + try: |
| 665 | + computed_parameters[key].close() |
| 666 | + except Exception: |
| 667 | + pass |
| 668 | + |
| 669 | + # output the response, optionally filtering based on provided jmespath query/search |
| 670 | + self.print(jmespath.search(query, response) if query else response) |
| 671 | + |
| 672 | + |
| 673 | + |
599 | 674 |
|
600 | 675 |
|
601 | 676 |
|
|
0 commit comments