yellowdog-python-examples 7.18.4__tar.gz → 7.18.5__tar.gz

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.
Files changed (79) hide show
  1. {yellowdog_python_examples-7.18.4/yellowdog_python_examples.egg-info → yellowdog_python_examples-7.18.5}/PKG-INFO +2 -2
  2. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/README.md +52 -14
  3. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/requirements.txt +1 -1
  4. yellowdog_python_examples-7.18.5/yellowdog_cli/__init__.py +1 -0
  5. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/create.py +39 -1
  6. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/list.py +66 -30
  7. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/show.py +21 -4
  8. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/submit.py +0 -3
  9. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/args.py +21 -11
  10. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/csv_data.py +5 -4
  11. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/load_config.py +8 -32
  12. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/misc_utils.py +32 -0
  13. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/printing.py +24 -13
  14. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/settings.py +3 -0
  15. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5/yellowdog_python_examples.egg-info}/PKG-INFO +2 -2
  16. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_python_examples.egg-info/requires.txt +1 -1
  17. yellowdog_python_examples-7.18.4/yellowdog_cli/__init__.py +0 -1
  18. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/LICENSE +0 -0
  19. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/PYPI_README.md +0 -0
  20. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/pyproject.toml +0 -0
  21. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/setup.cfg +0 -0
  22. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/tests/test_create_remove.py +0 -0
  23. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/tests/test_demos.py +0 -0
  24. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/tests/test_dryruns.py +0 -0
  25. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/tests/test_entrypoints.py +0 -0
  26. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/tests/test_gui.py +0 -0
  27. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/tests/test_list.py +0 -0
  28. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/tests/test_objects.py +0 -0
  29. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/tests/test_variable_processing.py +0 -0
  30. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/abort.py +0 -0
  31. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/admin.py +0 -0
  32. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/boost.py +0 -0
  33. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/cancel.py +0 -0
  34. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/cloudwizard.py +0 -0
  35. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/compare.py +0 -0
  36. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/delete.py +0 -0
  37. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/download.py +0 -0
  38. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/follow.py +0 -0
  39. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/format_json.py +0 -0
  40. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/hold.py +0 -0
  41. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/instantiate.py +0 -0
  42. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/jsonnet2json.py +0 -0
  43. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/provision.py +0 -0
  44. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/remove.py +0 -0
  45. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/resize.py +0 -0
  46. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/shutdown.py +0 -0
  47. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/start.py +0 -0
  48. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/terminate.py +0 -0
  49. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/upload.py +0 -0
  50. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/__init__.py +0 -0
  51. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/check_imports.py +0 -0
  52. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/cloudwizard_aws.py +0 -0
  53. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/cloudwizard_aws_types.py +0 -0
  54. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/cloudwizard_azure.py +0 -0
  55. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/cloudwizard_common.py +0 -0
  56. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/cloudwizard_gcp.py +0 -0
  57. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/compact_json.py +0 -0
  58. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/config_types.py +0 -0
  59. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/entity_utils.py +0 -0
  60. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/follow_utils.py +0 -0
  61. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/interactive.py +0 -0
  62. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/items.py +0 -0
  63. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/load_resources.py +0 -0
  64. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/property_names.py +0 -0
  65. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/provision_utils.py +0 -0
  66. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/rich_console_input_fixed.py +0 -0
  67. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/start_hold_common.py +0 -0
  68. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/submit_utils.py +0 -0
  69. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/type_check.py +0 -0
  70. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/upload_utils.py +0 -0
  71. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/validate_properties.py +0 -0
  72. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/variables.py +0 -0
  73. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/wrapper.py +0 -0
  74. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/utils/ydid_utils.py +0 -0
  75. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_cli/version.py +0 -0
  76. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_python_examples.egg-info/SOURCES.txt +0 -0
  77. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_python_examples.egg-info/dependency_links.txt +0 -0
  78. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_python_examples.egg-info/entry_points.txt +0 -0
  79. {yellowdog_python_examples-7.18.4 → yellowdog_python_examples-7.18.5}/yellowdog_python_examples.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yellowdog-python-examples
3
- Version: 7.18.4
3
+ Version: 7.18.5
4
4
  Summary: Python CLI commands using the YellowDog Python SDK
5
5
  Author-email: YellowDog Limited <support@yellowdog.co>
6
6
  Project-URL: Homepage, https://github.com/yellowdog/python-examples
@@ -20,7 +20,7 @@ Requires-Dist: requests
20
20
  Requires-Dist: rich==13.9.4
21
21
  Requires-Dist: tabulate>=0.9.0
22
22
  Requires-Dist: toml
23
- Requires-Dist: yellowdog-sdk>=9.3.3
23
+ Requires-Dist: yellowdog-sdk>=9.3.4
24
24
  Provides-Extra: jsonnet
25
25
  Requires-Dist: jsonnet; extra == "jsonnet"
26
26
  Provides-Extra: cloudwizard
@@ -84,7 +84,8 @@
84
84
  * [Resource Removal](#resource-removal)
85
85
  * [Resource Matching](#resource-matching)
86
86
  * [Resource Specification Definitions](#resource-specification-definitions)
87
- * [Generating Resource Specifications](#generating-resource-specifications)
87
+ * [Generating Resource Specifications using yd-list](#generating-resource-specifications-using-yd-list)
88
+ * [Usage Scenario: Moving Resources to a New Namespace](#usage-scenario-moving-resources-to-a-new-namespace)
88
89
  * [Preprocessing Resource Specifications](#preprocessing-resource-specifications)
89
90
  * [Keyrings](#keyrings)
90
91
  * [Credentials](#credentials)
@@ -131,7 +132,7 @@
131
132
  * [yd-compare](#yd-compare)
132
133
 
133
134
  <!-- Created by https://github.com/ekalinin/github-markdown-toc -->
134
- <!-- Added by: pwt, at: Mon Jul 28 21:41:59 BST 2025 -->
135
+ <!-- Added by: pwt, at: Tue Aug 5 13:52:07 BST 2025 -->
135
136
 
136
137
  <!--te-->
137
138
 
@@ -386,9 +387,11 @@ If all the required common properties are set using the command line or environm
386
387
 
387
388
  ## Support for `.env` Files
388
389
 
389
- Environment variables can also be set in a `.env` file, typically in the user's home directory. Entries in the `.env` file will not overwrite existing environment variables -- i.e., environment variables take precedence over entries in the `.env` file.
390
+ Environment variables can also be set in a `.env` file, typically in the user's home directory or the current working directory.
390
391
 
391
- Environment variables sourced from a `.env` file whose names start with `YD` will be reported on the command line. Variables that do not start with `YD` will not be reported, but they will still be applied.
392
+ Entries in the `.env` file will not overwrite existing environment variables -- i.e., environment variables take precedence over entries in the `.env` file. This precedence can be reversed by using the `--env-override` command line option.
393
+
394
+ Environment variables sourced from a `.env` file whose names start with `YD` will be reported on the command line. Variables whose names do not start with `YD` will not be reported, but they will still be applied.
392
395
 
393
396
  ## Variable Substitutions in Common Properties
394
397
 
@@ -1995,18 +1998,19 @@ When using the `yd-create` and `yd-remove` commands, note that an additional pro
1995
1998
  - `"Application"`
1996
1999
  - `"User"`
1997
2000
 
1998
- ## Generating Resource Specifications
2001
+ ## Generating Resource Specifications using `yd-list`
1999
2002
 
2000
- To generate example JSON specifications from resources already included in the platform, the `yd-list` command can be used with the `--details` option, and select the resources for which details are required. E.g.:
2003
+ To generate example JSON specifications from resources already included in the platform, the `yd-list` command can be used with the `--details`, `--substitute-ids`/`-U`, and `--strip-ids` options, and select the resources for which details are required. E.g.:
2001
2004
 
2002
2005
  ```shell
2003
- yd-list --keyrings --details
2004
- yd-list --source-templates --details
2005
- yd-list --compute-templates --details
2006
- yd-list --image-families --details
2006
+ yd-list --source-templates --details --substitute-ids --strip-ids
2007
+ yd-list --compute-templates --details --substitute-ids --strip-ids
2008
+ yd-list --image-families --details --substitute-ids --strip-ids
2007
2009
  ```
2008
2010
 
2009
- This will produce a list of resource specifications that can be copied and used directly with `yd-create` and `yd-remove`. Certain fields, such as the ID, will be ignored, with warnings. The detailed resource list can also be copied directly to an output file in addition to being displayed on the console:
2011
+ This will produce a list of resource specifications that can be copied and used directly with `yd-create` and `yd-remove`.
2012
+
2013
+ The detailed resource list can also be copied directly to an output file in addition to being displayed on the console using the `--output-file` option:
2010
2014
 
2011
2015
  ```shell
2012
2016
  yd-list yd-list --source-templates --details --output-file my-resources.json
@@ -2015,12 +2019,46 @@ yd-list yd-list --source-templates --details --output-file my-resources.json
2015
2019
  Alternatively, the `yd-show` command can be used with one or more `ydid` arguments to generate the details of each identified resource. E.g.,
2016
2020
 
2017
2021
  ```shell
2018
- yd-show -q ydid:cst:000000:cde265f8-0b17-4e0e-be1c-505174a620e4 > my-compute-source-template.json
2022
+ yd-show -q ydid:cst:000000:cde265f8-0b17-4e0e-be1c-505174a620e4 --substitute-ids --strip-ids --output-file my-compute-source-template.json
2019
2023
  ```
2020
2024
 
2021
2025
  would generate a JSON file that can be used with `yd-create` without alteration, or which could be edited.
2022
2026
 
2023
- Both `yd-list` and `yd-show` support the `--substitute-ids`/`-U` option. For Compute Requirement Template detailed output, this will substitute Compute Source Template IDs and Image Family IDs with their names, to make it easier to use the output acrosss YellowDog accounts.
2027
+ As illustrated above, both `yd-list` and `yd-show` support the `--substitute-ids`/`-U` option. For Compute Requirement Template detailed output, this will substitute Compute Source Template IDs and Image Family IDs with their names, to make it easier to reuse the outputs. For Compute Source Templates, Image Family IDs will be substituted. (Only Image Family IDs are substituted, not Image Group or Image IDs; if these are used in CRTs/CSTs, the JSON resource output may not be reusable.)
2028
+
2029
+ The `--strip-ids` option will remove any YellowDog IDs ('ydids') from the JSON output, as well as any other properties that are not required in order to use the output with `yd-create`.
2030
+
2031
+ ### Usage Scenario: Moving Resources to a New Namespace
2032
+
2033
+ In the following usage scenario, we want to move a set of resources from one namespace `ns-1`, to another `ns-2`. We'll move all compute source templates, compute requirement templates, and image families.
2034
+
2035
+ **Step 1: Capture the target resources in JSON files**
2036
+
2037
+ ```
2038
+ yd-list -q --compute-source-templates --namespace ns-1 --substitute-ids --strip-ids --auto-select-all --output-file csts.json
2039
+ yd-list -q --compute-requirement-templates --namespace ns-1 --substitute-ids --strip-ids --auto-select-all --output-file crts.json
2040
+ yd-list -q --image-families --namespace ns-1 --substitute-ids --strip-ids --auto-select-all --output-file ifs.json
2041
+ ```
2042
+
2043
+ **Step 2: Remove all target resources**
2044
+
2045
+ The following will remove all target resources included in the JSON resource files **without user confirmation**.
2046
+
2047
+ ```
2048
+ yd-remove -y csts.json crts.json ifs.json
2049
+ ```
2050
+
2051
+ **Step 3: Change the namespace in all the resources**
2052
+
2053
+ Use an editor's search and replace function, or a command line tool such as `sed` to replace all occurences of `"ns-1"` with `"ns-2`", for every `namespace` property, in each of the JSON files.
2054
+
2055
+ **Step 4: Recreate all resources in the new namespace**
2056
+
2057
+ ```
2058
+ yd-create -y csts.json crts.json ifs.json
2059
+ ```
2060
+
2061
+ Once the resources have been created successfully, the JSON files can be deleted (or retained for your records).
2024
2062
 
2025
2063
  ## Preprocessing Resource Specifications
2026
2064
 
@@ -2402,7 +2440,7 @@ Example:
2402
2440
 
2403
2441
  ### Creating and Regenerating Application Keys
2404
2442
 
2405
- When Application is created its Application Key ID and Secret will be displayed (even if the `--quiet` option is used).
2443
+ When an Application is created its Application Key ID and Secret will be displayed (even if the `--quiet` option is used).
2406
2444
 
2407
2445
  When an Application is updated, the `--regenerate-app-keys` option can be used. This will invalidate the current Application key and secret, revoke any Keyring access, and generate a new key and secret which will be displayed.
2408
2446
 
@@ -5,4 +5,4 @@ requests
5
5
  rich == 13.9.4
6
6
  tabulate >= 0.9.0
7
7
  toml
8
- yellowdog-sdk >= 9.3.3
8
+ yellowdog-sdk >= 9.3.4
@@ -0,0 +1 @@
1
+ __version__ = "7.18.5"
@@ -532,7 +532,7 @@ def create_image_family(resource):
532
532
  if e.response.status_code == 404:
533
533
  # This will create the Image Family and all of its constituent
534
534
  # Image Group/Image resources
535
- image_family = CLIENT.images_client.add_image_family(image_family)
535
+ image_family = _create_image_family(image_family, fq_name)
536
536
  print_log(f"Created Machine Image Family '{fq_name}' ('{image_family.id}')")
537
537
  if ARGS_PARSER.quiet:
538
538
  print(image_family.id)
@@ -1251,6 +1251,44 @@ def update_user(resource: Dict):
1251
1251
  print_log(f"Nothing to do for User '{username}' ({user.id})")
1252
1252
 
1253
1253
 
1254
+ def _create_image_family(
1255
+ image_family: MachineImageFamily, fq_name: str
1256
+ ) -> MachineImageFamily:
1257
+ """
1258
+ Creates a new image family. Only one image group can be added at the time of
1259
+ image family creation, so any additional image groups must be added separately.
1260
+ """
1261
+
1262
+ # Remove all except the first image group; keep the rest as a separate list
1263
+ image_groups = image_family.imageGroups
1264
+ if image_groups is not None:
1265
+ image_family.imageGroups = image_groups[:1]
1266
+ image_groups = image_groups[1:] # Remaining image groups
1267
+
1268
+ # Create the image family
1269
+ try:
1270
+ image_family = CLIENT.images_client.add_image_family(image_family)
1271
+ except Exception as e:
1272
+ raise Exception(f"Failed to create Machine Image Family '{fq_name}': {e}")
1273
+
1274
+ if image_groups is None or len(image_groups) == 0:
1275
+ return image_family
1276
+
1277
+ # Create any additional image groups
1278
+ for image_group in image_groups:
1279
+ try:
1280
+ image_group = CLIENT.images_client.add_image_group(
1281
+ image_family, image_group
1282
+ )
1283
+ except Exception as e:
1284
+ raise Exception(
1285
+ f"Failed to add Machine Image Group '{image_group.name}' to "
1286
+ f"Image Family '{fq_name}': {e}"
1287
+ )
1288
+
1289
+ return image_family
1290
+
1291
+
1254
1292
  # Entry point
1255
1293
  if __name__ == "__main__":
1256
1294
  main()
@@ -75,11 +75,16 @@ from yellowdog_cli.utils.printing import (
75
75
  sorted_objects,
76
76
  )
77
77
  from yellowdog_cli.utils.settings import (
78
+ PROP_GROUPS,
79
+ PROP_RESOURCE,
78
80
  RN_ALLOWANCE,
81
+ RN_APPLICATION,
82
+ RN_GROUP,
79
83
  RN_IMAGE_FAMILY,
80
84
  RN_KEYRING,
81
85
  RN_NUMERIC_ATTRIBUTE_DEFINITION,
82
86
  RN_REQUIREMENT_TEMPLATE,
87
+ RN_ROLE,
83
88
  RN_SOURCE_TEMPLATE,
84
89
  RN_STRING_ATTRIBUTE_DEFINITION,
85
90
  )
@@ -104,7 +109,7 @@ def main():
104
109
  ARGS_PARSER.details = True
105
110
 
106
111
  if ARGS_PARSER.details and ARGS_PARSER.strip_ids:
107
- print_log("Omitting YellowDog IDs from detailed JSON objects")
112
+ print_log("Omitting YellowDog IDs (etc.) from detailed JSON objects")
108
113
 
109
114
  if ARGS_PARSER.output_file and ARGS_PARSER.details:
110
115
  if exists(ARGS_PARSER.output_file):
@@ -584,7 +589,7 @@ def list_compute_requirement_templates():
584
589
  CLIENT,
585
590
  CLIENT.compute_client.get_compute_requirement_template(cr_template.id),
586
591
  ),
587
- RN_REQUIREMENT_TEMPLATE,
592
+ {PROP_RESOURCE: RN_REQUIREMENT_TEMPLATE},
588
593
  )
589
594
  for cr_template in cr_templates
590
595
  ]
@@ -633,7 +638,7 @@ def list_compute_source_templates():
633
638
  CLIENT,
634
639
  CLIENT.compute_client.get_compute_source_template(cs_template.id),
635
640
  ),
636
- RN_SOURCE_TEMPLATE,
641
+ {PROP_RESOURCE: RN_SOURCE_TEMPLATE},
637
642
  )
638
643
  for cs_template in cs_templates
639
644
  ]
@@ -662,7 +667,7 @@ def list_keyrings():
662
667
 
663
668
  # Show details
664
669
  print_yd_object_list(
665
- [(keyring, RN_KEYRING) for keyring in select(CLIENT, keyrings)]
670
+ [(keyring, {PROP_RESOURCE: RN_KEYRING}) for keyring in select(CLIENT, keyrings)]
666
671
  )
667
672
 
668
673
 
@@ -712,7 +717,7 @@ def list_image_families():
712
717
  image_families = [
713
718
  (
714
719
  CLIENT.images_client.get_image_family_by_id(image_family_summary.id),
715
- RN_IMAGE_FAMILY,
720
+ {PROP_RESOURCE: RN_IMAGE_FAMILY},
716
721
  )
717
722
  for image_family_summary in image_family_summaries
718
723
  ]
@@ -809,7 +814,10 @@ def list_allowances():
809
814
 
810
815
  # Show details
811
816
  print_yd_object_list(
812
- [(allowance, RN_ALLOWANCE) for allowance in select(CLIENT, allowances)]
817
+ [
818
+ (allowance, {PROP_RESOURCE: RN_ALLOWANCE})
819
+ for allowance in select(CLIENT, allowances)
820
+ ]
813
821
  )
814
822
 
815
823
 
@@ -841,11 +849,13 @@ def list_attribute_definitions():
841
849
  attribute_definition_list = [
842
850
  (
843
851
  attribute,
844
- (
845
- RN_NUMERIC_ATTRIBUTE_DEFINITION
846
- if "Numeric" in attribute["type"]
847
- else RN_STRING_ATTRIBUTE_DEFINITION
848
- ),
852
+ {
853
+ PROP_RESOURCE: (
854
+ RN_NUMERIC_ATTRIBUTE_DEFINITION
855
+ if "Numeric" in attribute["type"]
856
+ else RN_STRING_ATTRIBUTE_DEFINITION
857
+ )
858
+ },
849
859
  )
850
860
  for attribute in select(
851
861
  CLIENT,
@@ -904,13 +914,20 @@ def list_users():
904
914
  print_numbered_object_list(CLIENT, users, object_type_name="User")
905
915
  return
906
916
 
907
- for selected_user in select(CLIENT, users, object_type_name="User"):
908
- add_groups_field = {
909
- "groups": [
910
- group.name for group in get_user_groups(CLIENT, selected_user.id)
911
- ]
912
- }
913
- print_yd_object(selected_user, add_fields=add_groups_field)
917
+ # Add the list of groups to the user details
918
+ print_yd_object_list(
919
+ [
920
+ (
921
+ user,
922
+ {
923
+ PROP_GROUPS: [
924
+ group.name for group in get_user_groups(CLIENT, user.id)
925
+ ]
926
+ },
927
+ )
928
+ for user in select(CLIENT, users)
929
+ ]
930
+ )
914
931
 
915
932
 
916
933
  def list_applications():
@@ -929,13 +946,22 @@ def list_applications():
929
946
  print_numbered_object_list(CLIENT, applications, object_type_name="Application")
930
947
  return
931
948
 
932
- for selected_app in select(CLIENT, applications, object_type_name="Application"):
933
- add_groups_field = {
934
- "groups": [
935
- group.name for group in get_application_groups(CLIENT, selected_app.id)
936
- ]
937
- }
938
- print_yd_object(selected_app, add_fields=add_groups_field)
949
+ # Add the list of group names for each application
950
+ print_yd_object_list(
951
+ [
952
+ (
953
+ application,
954
+ {
955
+ PROP_GROUPS: [
956
+ group.name
957
+ for group in get_application_groups(CLIENT, application.id)
958
+ ],
959
+ PROP_RESOURCE: RN_APPLICATION,
960
+ },
961
+ )
962
+ for application in select(CLIENT, applications)
963
+ ]
964
+ )
939
965
 
940
966
 
941
967
  def list_groups():
@@ -951,15 +977,24 @@ def list_groups():
951
977
  group_summaries.sort(key=lambda group: group.name if group.name is not None else "")
952
978
 
953
979
  groups: List[Group] = [
954
- CLIENT.account_client.get_group(x.id) for x in group_summaries
980
+ CLIENT.account_client.get_group(group.id) for group in group_summaries
955
981
  ]
956
982
 
957
983
  if not ARGS_PARSER.details:
958
984
  print_numbered_object_list(CLIENT, groups, object_type_name="Group")
959
985
  return
960
986
 
961
- for selected_users in select(CLIENT, groups, object_type_name="Group"):
962
- print_yd_object(selected_users)
987
+ selected_groups = select(CLIENT, groups)
988
+
989
+ # If stripping IDs, just supply the list of role names;
990
+ # subverts the type
991
+ if ARGS_PARSER.strip_ids:
992
+ for group in selected_groups:
993
+ group.roles = [group_role.role.name for group_role in group.roles]
994
+
995
+ print_yd_object_list(
996
+ [(group, {PROP_RESOURCE: RN_GROUP}) for group in selected_groups]
997
+ )
963
998
 
964
999
 
965
1000
  def list_roles():
@@ -986,8 +1021,9 @@ def list_roles():
986
1021
  print_numbered_object_list(CLIENT, roles, object_type_name="Role")
987
1022
  return
988
1023
 
989
- for selected_users in select(CLIENT, roles, object_type_name="Role"):
990
- print_yd_object(selected_users)
1024
+ print_yd_object_list(
1025
+ [(role, {PROP_RESOURCE: RN_ROLE}) for role in select(CLIENT, roles)]
1026
+ )
991
1027
 
992
1028
 
993
1029
  def list_permissions():
@@ -8,11 +8,18 @@ from yellowdog_client.model import ConfiguredWorkerPool
8
8
 
9
9
  from yellowdog_cli.list import get_keyring
10
10
  from yellowdog_cli.utils.entity_utils import (
11
+ get_application_groups,
11
12
  substitute_ids_for_names_in_crt,
12
13
  substitute_image_family_id_for_name_in_cst,
13
14
  )
14
- from yellowdog_cli.utils.printing import print_error, print_log, print_yd_object
15
+ from yellowdog_cli.utils.printing import (
16
+ print_error,
17
+ print_log,
18
+ print_to_file,
19
+ print_yd_object,
20
+ )
15
21
  from yellowdog_cli.utils.settings import (
22
+ PROP_GROUPS,
16
23
  RESOURCE_PROPERTY_NAME,
17
24
  RN_ALLOWANCE,
18
25
  RN_APPLICATION,
@@ -36,11 +43,13 @@ def main():
36
43
  # and the 'quiet' option is enabled
37
44
  generate_json_list = len(ARGS_PARSER.yellowdog_ids) > 1 and ARGS_PARSER.quiet
38
45
 
39
- if ARGS_PARSER.details and ARGS_PARSER.strip_ids:
40
- print_log("Omitting YellowDog IDs from detailed JSON objects")
46
+ if ARGS_PARSER.strip_ids:
47
+ print_log("Omitting YellowDog IDs (etc.) from detailed JSON objects")
41
48
 
42
49
  if generate_json_list:
43
50
  print("[")
51
+ if ARGS_PARSER.output_file is not None:
52
+ print_to_file("[", ARGS_PARSER.output_file)
44
53
 
45
54
  for index, ydid in enumerate(ARGS_PARSER.yellowdog_ids):
46
55
  if generate_json_list:
@@ -53,6 +62,8 @@ def main():
53
62
 
54
63
  if generate_json_list:
55
64
  print("]")
65
+ if ARGS_PARSER.output_file is not None:
66
+ print_to_file("]", ARGS_PARSER.output_file)
56
67
 
57
68
 
58
69
  def show_details(ydid: str, initial_indent: int = 0, with_final_comma: bool = False):
@@ -210,11 +221,17 @@ def show_details(ydid: str, initial_indent: int = 0, with_final_comma: bool = Fa
210
221
 
211
222
  elif ydid_type == YDIDType.APPLICATION:
212
223
  print_log(f"Showing details of Application ID '{ydid}'")
224
+ group_names = [group.name for group in get_application_groups(CLIENT, ydid)]
213
225
  print_yd_object(
214
226
  CLIENT.account_client.get_application(ydid),
215
227
  initial_indent=initial_indent,
216
228
  with_final_comma=with_final_comma,
217
- add_fields=({RESOURCE_PROPERTY_NAME: RN_APPLICATION}),
229
+ add_fields=(
230
+ {
231
+ PROP_GROUPS: group_names,
232
+ RESOURCE_PROPERTY_NAME: RN_APPLICATION,
233
+ }
234
+ ),
218
235
  )
219
236
 
220
237
  elif ydid_type == YDIDType.USER:
@@ -23,8 +23,6 @@ from yellowdog_client.model import (
23
23
  RunSpecification,
24
24
  Task,
25
25
  TaskData,
26
- TaskErrorMatcher,
27
- TaskErrorType,
28
26
  TaskGroup,
29
27
  TaskInput,
30
28
  TaskInputSource,
@@ -56,7 +54,6 @@ from yellowdog_cli.utils.printing import (
56
54
  print_log,
57
55
  print_numbered_strings,
58
56
  print_warning,
59
- print_yd_object,
60
57
  )
61
58
  from yellowdog_cli.utils.property_names import *
62
59
  from yellowdog_cli.utils.settings import (
@@ -107,7 +107,6 @@ class CLIParser:
107
107
  required=False,
108
108
  help="disable colouring and text wrapping in command output",
109
109
  )
110
-
111
110
  parser.add_argument(
112
111
  "--quiet",
113
112
  "-q",
@@ -115,6 +114,12 @@ class CLIParser:
115
114
  required=False,
116
115
  help="suppress (non-error, non-interactive) status and progress messages",
117
116
  )
117
+ parser.add_argument(
118
+ "--env-override",
119
+ action="store_true",
120
+ required=False,
121
+ help="values in '.env' file override values in the environment",
122
+ )
118
123
 
119
124
  # Module-specific argument sets
120
125
  if not any(module in sys.argv[0] for module in ["compare"]):
@@ -663,16 +668,6 @@ class CLIParser:
663
668
  required=False,
664
669
  help="show the full JSON representation of objects",
665
670
  )
666
- parser.add_argument(
667
- "--output-file",
668
- type=str,
669
- required=False,
670
- help=(
671
- "if specified, the 'details' JSON resource listing will also be written "
672
- "to the nominated output file"
673
- ),
674
- metavar="<output-file>",
675
- )
676
671
  parser.add_argument(
677
672
  "--auto-select-all",
678
673
  action="store_true",
@@ -1194,6 +1189,16 @@ class CLIParser:
1194
1189
  "(implies '--details')"
1195
1190
  ),
1196
1191
  )
1192
+ parser.add_argument(
1193
+ "--output-file",
1194
+ type=str,
1195
+ required=False,
1196
+ help=(
1197
+ "if specified, the detailed JSON resource listing will also be written "
1198
+ "to the nominated output file"
1199
+ ),
1200
+ metavar="<output-file>",
1201
+ )
1197
1202
 
1198
1203
  if "compare" in sys.argv[0]:
1199
1204
  parser.add_argument(
@@ -1265,6 +1270,11 @@ class CLIParser:
1265
1270
  def quiet(self) -> Optional[bool]:
1266
1271
  return self.args.quiet
1267
1272
 
1273
+ @property
1274
+ @allow_missing_attribute
1275
+ def env_override(self) -> Optional[bool]:
1276
+ return self.args.env_override
1277
+
1268
1278
  @property
1269
1279
  @allow_missing_attribute
1270
1280
  def work_req_file(self) -> Optional[str]:
@@ -8,7 +8,7 @@ from ast import literal_eval
8
8
  from collections import OrderedDict
9
9
  from json import load as json_load
10
10
  from os.path import relpath
11
- from typing import Dict, List, Optional
11
+ from typing import Dict, List, Optional, Tuple
12
12
 
13
13
  from toml import load as toml_load
14
14
 
@@ -290,7 +290,7 @@ USED_FILE_INDEXES = []
290
290
 
291
291
  def get_csv_file_index(
292
292
  csv_filename: str, task_groups: List[Dict]
293
- ) -> [str, Optional[int]]:
293
+ ) -> Tuple[str, Optional[int]]:
294
294
  """
295
295
  Check if the CSV filename ends in an integer index (':<integer>'),
296
296
  or in a Task Group name (':<task_group_name>').
@@ -378,8 +378,6 @@ def csv_expand_toml_tasks(
378
378
  (config_wr.add_yd_env_vars, ADD_YD_ENV_VARS),
379
379
  (config_wr.always_upload, ALWAYS_UPLOAD),
380
380
  (config_wr.args, ARGS),
381
- (config_wr.task_data_inputs, TASK_DATA_INPUTS),
382
- (config_wr.task_data_outputs, TASK_DATA_OUTPUTS),
383
381
  (config_wr.docker_env, DOCKER_ENV),
384
382
  (config_wr.docker_options, DOCKER_OPTIONS),
385
383
  (config_wr.docker_password, DOCKER_PASSWORD),
@@ -393,8 +391,11 @@ def csv_expand_toml_tasks(
393
391
  (config_wr.outputs_optional, OUTPUTS_OPTIONAL),
394
392
  (config_wr.outputs_other, OUTPUTS_OTHER),
395
393
  (config_wr.outputs_required, OUTPUTS_REQUIRED),
394
+ (config_wr.set_task_names, SET_TASK_NAMES),
396
395
  (config_wr.task_data, TASK_DATA),
397
396
  (config_wr.task_data_file, TASK_DATA_FILE),
397
+ (config_wr.task_data_inputs, TASK_DATA_INPUTS),
398
+ (config_wr.task_data_outputs, TASK_DATA_OUTPUTS),
398
399
  (config_wr.task_group_name, TASK_GROUP_NAME), # Note: oddity
399
400
  (config_wr.task_level_timeout, TASK_LEVEL_TIMEOUT),
400
401
  (config_wr.task_name, TASK_NAME),
@@ -9,7 +9,6 @@ from pathlib import Path
9
9
  from sys import exit
10
10
  from typing import Dict
11
11
 
12
- from dotenv import dotenv_values, find_dotenv, load_dotenv
13
12
  from toml import TomlDecodeError
14
13
 
15
14
  from yellowdog_cli.utils.args import ARGS_PARSER
@@ -18,7 +17,14 @@ from yellowdog_cli.utils.config_types import (
18
17
  ConfigWorkerPool,
19
18
  ConfigWorkRequirement,
20
19
  )
21
- from yellowdog_cli.utils.misc_utils import pathname_relative_to_config_file
20
+ from yellowdog_cli.utils.misc_utils import (
21
+ load_dotenv_file,
22
+ pathname_relative_to_config_file,
23
+ )
24
+
25
+ # Load additional environment variables as early as possible
26
+ load_dotenv_file()
27
+
22
28
  from yellowdog_cli.utils.printing import print_error, print_log
23
29
  from yellowdog_cli.utils.property_names import *
24
30
  from yellowdog_cli.utils.settings import (
@@ -102,10 +108,6 @@ def load_config_common() -> ConfigCommon:
102
108
  common_section_imported.update(common_section)
103
109
  common_section = common_section_imported
104
110
 
105
- # Load extra environment variables from a .env file if it exists;
106
- # do not override existing variables (environment takes precedence)
107
- _load_dotenv()
108
-
109
111
  # Replace common section properties with command line or
110
112
  # environment variable overrides. Precedence is:
111
113
  # command line > environment variable > config file
@@ -453,29 +455,3 @@ def load_config_worker_pool() -> ConfigWorkerPool:
453
455
  except ValueError as e:
454
456
  print_error(f"Invalid type for configuration: {e}")
455
457
  exit(1)
456
-
457
-
458
- def _load_dotenv():
459
- """
460
- Load extra environment variables from a .env file if it exists.
461
- Do not override existing variables (environment takes precedence).
462
- Report on YD vars that are taken from .env.
463
- """
464
- dotenv_file = find_dotenv()
465
- if dotenv_file == "":
466
- return
467
-
468
- dotenv_yd_substitutions = [ # Find 'YD' variables
469
- f"'{key}'"
470
- for key in dotenv_values(dotenv_file).keys()
471
- if key.startswith("YD") and os.environ.get(key) is None
472
- ]
473
-
474
- if len(dotenv_yd_substitutions) > 0:
475
- print_log(
476
- f"Adding 'YD' environment variables from '.env' file '{dotenv_file}': "
477
- f"{', '.join(dotenv_yd_substitutions)}"
478
- )
479
-
480
- # Actually load the variables (including non-'YD' variables)
481
- load_dotenv(dotenv_file, override=False)
@@ -2,6 +2,7 @@
2
2
  General utility functions.
3
3
  """
4
4
 
5
+ import os
5
6
  import re
6
7
  from dataclasses import dataclass
7
8
  from datetime import datetime, timezone
@@ -9,6 +10,7 @@ from os.path import join, normpath, relpath
9
10
  from typing import List, Optional
10
11
  from urllib.parse import urlparse
11
12
 
13
+ from dotenv import dotenv_values, find_dotenv, load_dotenv
12
14
  from yellowdog_client.model import (
13
15
  ComputeRequirement,
14
16
  ConfiguredWorkerPool,
@@ -16,6 +18,8 @@ from yellowdog_client.model import (
16
18
  WorkRequirement,
17
19
  )
18
20
 
21
+ from yellowdog_cli.utils.args import ARGS_PARSER
22
+ from yellowdog_cli.utils.printing import print_log
19
23
  from yellowdog_cli.utils.settings import NAMESPACE_OBJECT_STORE_PREFIX_SEPARATOR
20
24
 
21
25
  UTCNOW = datetime.now(timezone.utc)
@@ -236,3 +240,31 @@ def format_yd_name(yd_name: str, add_prefix: bool = True) -> str:
236
240
 
237
241
  # Mustn't exceed 60 chars
238
242
  return new_yd_name[:60]
243
+
244
+
245
+ def load_dotenv_file():
246
+ """
247
+ Load extra environment variables from a .env file if it exists.
248
+ Do not override existing variables (environment takes precedence)
249
+ unless --env-override option is set.
250
+ Report on YD vars that are taken from .env.
251
+ """
252
+ dotenv_file = find_dotenv()
253
+ if dotenv_file == "":
254
+ return
255
+
256
+ dotenv_yd_substitutions = [ # Find 'YD' variables
257
+ f"'{key}'"
258
+ for key in dotenv_values(dotenv_file).keys()
259
+ if key.startswith("YD")
260
+ and (os.environ.get(key) is None or ARGS_PARSER.env_override)
261
+ ]
262
+
263
+ if len(dotenv_yd_substitutions) > 0:
264
+ print_log(
265
+ f"Adding 'YD' environment variables from '.env' file '{dotenv_file}': "
266
+ f"{', '.join(dotenv_yd_substitutions)}"
267
+ )
268
+
269
+ # Actually load the variables (including non-'YD' variables)
270
+ load_dotenv(dotenv_file, override=ARGS_PARSER.env_override)
@@ -71,10 +71,12 @@ from yellowdog_cli.utils.settings import (
71
71
  MAX_LINES_COLOURED_FORMATTING,
72
72
  MAX_TABLE_DESCRIPTION,
73
73
  NAMESPACE_OBJECT_STORE_PREFIX_SEPARATOR,
74
+ PROP_ACCESS_DELEGATES,
75
+ PROP_ADMIN_GROUP,
76
+ PROP_CREATED_BY_USER_ID,
74
77
  PROP_CREATED_TIME,
75
78
  PROP_ID,
76
79
  PROP_INSTANCE_PRICING,
77
- PROP_RESOURCE,
78
80
  PROP_SUPPORTING_RESOURCE_CREATED,
79
81
  PROP_TRAITS,
80
82
  WARNING_STYLE,
@@ -98,10 +100,13 @@ class PrintLogHighlighter(RegexHighlighter):
98
100
  r"(?P<date_time>[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]"
99
101
  r" [0-9][0-9]:[0-9][0-9]:[0-9][0-9])",
100
102
  r"(?P<quoted>'[a-zA-Z0-9-._=;:\/\\\[\]{}+#@$£%\^&\*\(\)~`<>?]*')",
101
- r"(?P<ydid>ydid:[a-z]*:[0-9ABCDEF]*:[0-9abcdef-]*)",
102
103
  r"(?P<ydid>ydid:[a-z]*:[0-9abcdef-]*)",
104
+ r"(?P<ydid>ydid:[a-z]*:[0-9ABCDEF]*:[0-9abcdef-]*)",
103
105
  r"(?P<ydid>ydid:[a-z]*:[0-9ABCDEF]*:[0-9abcdef-]*:[0-9]*)",
104
106
  r"(?P<ydid>ydid:[a-z]*:[0-9ABCDEF]*:[0-9abcdef-]*:[0-9]*:[0-9]*)",
107
+ r"(?P<ydid>ydid:[a-z]*:[0-9ABCDEF]*:[0-9ABCDEF]*:[0-9abcdef-]*)",
108
+ r"(?P<ydid>ydid:[a-z]*:[0-9ABCDEF]*:[0-9ABCDEF]*:[0-9abcdef-]*:[0-9]*)",
109
+ r"(?P<ydid>ydid:[a-z]*:[0-9ABCDEF]*:[0-9ABCDEF]*:[0-9abcdef-]*:[0-9]*:[0-9]*)",
105
110
  r"(?P<url>(https?):((//)|(\\\\))+[\w\d:#@%/;$~_?\+-=\\\.&]*)",
106
111
  ] + HIGHLIGHTED_STATES
107
112
 
@@ -120,6 +125,9 @@ class PrintTableHighlighter(RegexHighlighter):
120
125
  r"(?P<ydid>ydid:[a-z]*:[0-9abcdef-]*)",
121
126
  r"(?P<ydid>ydid:[a-z]*:[0-9ABCDEF]*:[0-9abcdef-]*:[0-9]*)",
122
127
  r"(?P<ydid>ydid:[a-z]*:[0-9ABCDEF]*:[0-9abcdef-]*:[0-9]*:[0-9]*)",
128
+ r"(?P<ydid>ydid:[a-z]*:[0-9ABCDEF]*:[0-9ABCDEF]*:[0-9abcdef-]*)",
129
+ r"(?P<ydid>ydid:[a-z]*:[0-9ABCDEF]*:[0-9ABCDEF]*:[0-9abcdef-]*:[0-9]*)",
130
+ r"(?P<ydid>ydid:[a-z]*:[0-9ABCDEF]*:[0-9ABCDEF]*:[0-9abcdef-]*:[0-9]*:[0-9]*)",
123
131
  ] + HIGHLIGHTED_STATES
124
132
 
125
133
 
@@ -227,10 +235,12 @@ def print_warning(
227
235
  TYPE_MAP = {
228
236
  AWSAvailabilityZone: "AWS Availability Zones",
229
237
  Allowance: "Allowance",
238
+ Application: "Application",
230
239
  ComputeRequirement: "Compute Requirement",
231
240
  ComputeRequirementTemplateSummary: "Compute Requirement Template",
232
241
  ComputeSourceTemplateSummary: "Compute Source Template",
233
242
  ConfiguredWorkerPool: "Configured Worker Pool",
243
+ Group: "Group",
234
244
  KeyringSummary: "Keyring",
235
245
  MachineImageFamilySummary: "Machine Image Family",
236
246
  NamespacePolicy: "Namespace Policy",
@@ -238,8 +248,10 @@ TYPE_MAP = {
238
248
  ObjectPath: "Object Path",
239
249
  PermissionDetail: "Permission",
240
250
  ProvisionedWorkerPool: "Provisioned Worker Pool",
251
+ Role: "Role",
241
252
  Task: "Task",
242
253
  TaskGroup: "Task Group",
254
+ User: "User",
243
255
  WorkRequirementSummary: "Work Requirement",
244
256
  Worker: "Worker",
245
257
  WorkerPoolSummary: "Worker Pool",
@@ -1048,7 +1060,7 @@ def print_json(
1048
1060
  CONSOLE_JSON.print(json_string, soft_wrap=True)
1049
1061
 
1050
1062
  if ARGS_PARSER.output_file is not None: # Also output to a nominated file
1051
- _print_to_file(
1063
+ print_to_file(
1052
1064
  json_string=json_string,
1053
1065
  output_file=ARGS_PARSER.output_file,
1054
1066
  with_final_comma=with_final_comma,
@@ -1081,6 +1093,9 @@ def print_yd_object(
1081
1093
  if k
1082
1094
  not in [
1083
1095
  PROP_ID,
1096
+ PROP_ACCESS_DELEGATES,
1097
+ PROP_ADMIN_GROUP,
1098
+ PROP_CREATED_BY_USER_ID,
1084
1099
  PROP_CREATED_TIME,
1085
1100
  PROP_INSTANCE_PRICING,
1086
1101
  PROP_SUPPORTING_RESOURCE_CREATED,
@@ -1111,7 +1126,7 @@ def print_yd_object(
1111
1126
 
1112
1127
 
1113
1128
  def print_yd_object_list(
1114
- objects: List[Tuple[Any, Optional[str]]], # Tuples are (object, resource_type_name)
1129
+ objects: List[Tuple[Any, Optional[Dict]]],
1115
1130
  ):
1116
1131
  """
1117
1132
  Print a JSON list of objects.
@@ -1123,24 +1138,20 @@ def print_yd_object_list(
1123
1138
  if len(objects) > 1:
1124
1139
  print("[")
1125
1140
  if ARGS_PARSER.output_file is not None:
1126
- _print_to_file("[", ARGS_PARSER.output_file)
1141
+ print_to_file("[", ARGS_PARSER.output_file)
1127
1142
 
1128
- for index, (object_, resource_type_name) in enumerate(objects):
1143
+ for index, (object_, add_fields) in enumerate(objects):
1129
1144
  print_yd_object(
1130
1145
  object_,
1131
1146
  initial_indent=2 if len(objects) > 1 else 0,
1132
1147
  with_final_comma=(True if index < len(objects) - 1 else False),
1133
- add_fields=(
1134
- {}
1135
- if resource_type_name is None
1136
- else {PROP_RESOURCE: resource_type_name}
1137
- ),
1148
+ add_fields=add_fields,
1138
1149
  )
1139
1150
 
1140
1151
  if len(objects) > 1:
1141
1152
  print("]")
1142
1153
  if ARGS_PARSER.output_file is not None:
1143
- _print_to_file("]", ARGS_PARSER.output_file)
1154
+ print_to_file("]", ARGS_PARSER.output_file)
1144
1155
 
1145
1156
 
1146
1157
  def print_worker_pool(
@@ -1501,7 +1512,7 @@ def print_event(event: str, id_type: YDIDType):
1501
1512
  FIRST_OUTPUT_TO_FILE = True # Determine whether to 'write' or 'append'
1502
1513
 
1503
1514
 
1504
- def _print_to_file(json_string: str, output_file: str, with_final_comma: bool = False):
1515
+ def print_to_file(json_string: str, output_file: str, with_final_comma: bool = False):
1505
1516
  """
1506
1517
  Dump details output to a file.
1507
1518
  """
@@ -133,7 +133,10 @@ RN_UPDATE_GROUP_REQUEST = "UpdateGroupRequest"
133
133
  RN_USER = "User"
134
134
 
135
135
  # Property Names
136
+ PROP_ACCESS_DELEGATES = "accessDelegates"
137
+ PROP_ADMIN_GROUP = "adminGroup"
136
138
  PROP_AUTOSCALING_MAX_NODES = "autoscalingMaxNodes"
139
+ PROP_CREATED_BY_USER_ID = "createdByUserId"
137
140
  PROP_CREATED_TIME = "createdTime"
138
141
  PROP_CREDENTIAL = "credential"
139
142
  PROP_CST_ID = "sourceTemplateId"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yellowdog-python-examples
3
- Version: 7.18.4
3
+ Version: 7.18.5
4
4
  Summary: Python CLI commands using the YellowDog Python SDK
5
5
  Author-email: YellowDog Limited <support@yellowdog.co>
6
6
  Project-URL: Homepage, https://github.com/yellowdog/python-examples
@@ -20,7 +20,7 @@ Requires-Dist: requests
20
20
  Requires-Dist: rich==13.9.4
21
21
  Requires-Dist: tabulate>=0.9.0
22
22
  Requires-Dist: toml
23
- Requires-Dist: yellowdog-sdk>=9.3.3
23
+ Requires-Dist: yellowdog-sdk>=9.3.4
24
24
  Provides-Extra: jsonnet
25
25
  Requires-Dist: jsonnet; extra == "jsonnet"
26
26
  Provides-Extra: cloudwizard
@@ -5,7 +5,7 @@ requests
5
5
  rich==13.9.4
6
6
  tabulate>=0.9.0
7
7
  toml
8
- yellowdog-sdk>=9.3.3
8
+ yellowdog-sdk>=9.3.4
9
9
 
10
10
  [cloudwizard]
11
11
  boto3
@@ -1 +0,0 @@
1
- __version__ = "7.18.4"