yellowdog-python-examples 7.8.8__tar.gz → 7.9.1__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 (76) hide show
  1. {yellowdog_python_examples-7.8.8/yellowdog_python_examples.egg-info → yellowdog_python_examples-7.9.1}/PKG-INFO +7 -4
  2. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/PYPI_README.md +6 -3
  3. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/README.md +89 -31
  4. yellowdog_python_examples-7.9.1/yd_commands/__init__.py +1 -0
  5. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/args.py +12 -0
  6. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/create.py +61 -1
  7. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/interactive.py +5 -3
  8. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/list.py +38 -0
  9. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/load_config.py +7 -1
  10. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/load_resources.py +4 -0
  11. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/printing.py +27 -1
  12. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/remove.py +32 -1
  13. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/settings.py +2 -0
  14. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/shutdown.py +17 -7
  15. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1/yellowdog_python_examples.egg-info}/PKG-INFO +7 -4
  16. yellowdog_python_examples-7.8.8/yd_commands/__init__.py +0 -1
  17. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/LICENSE +0 -0
  18. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/pyproject.toml +0 -0
  19. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/requirements.txt +0 -0
  20. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/setup.cfg +0 -0
  21. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/setup.py +0 -0
  22. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/tests/test_create_remove.py +0 -0
  23. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/tests/test_demos.py +0 -0
  24. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/tests/test_dryruns.py +0 -0
  25. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/tests/test_entrypoints.py +0 -0
  26. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/tests/test_gui.py +0 -0
  27. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/tests/test_list.py +0 -0
  28. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/tests/test_objects.py +0 -0
  29. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/tests/test_variable_processing.py +0 -0
  30. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/abort.py +0 -0
  31. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/admin.py +0 -0
  32. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/boost.py +0 -0
  33. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/cancel.py +0 -0
  34. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/check_imports.py +0 -0
  35. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/cloudwizard.py +0 -0
  36. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/cloudwizard_aws.py +0 -0
  37. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/cloudwizard_aws_types.py +0 -0
  38. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/cloudwizard_azure.py +0 -0
  39. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/cloudwizard_common.py +0 -0
  40. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/cloudwizard_gcp.py +0 -0
  41. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/compact_json.py +0 -0
  42. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/config_types.py +0 -0
  43. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/csv_data.py +0 -0
  44. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/delete.py +0 -0
  45. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/download.py +0 -0
  46. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/follow.py +0 -0
  47. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/follow_utils.py +0 -0
  48. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/format_json.py +0 -0
  49. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/hold.py +0 -0
  50. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/id_utils.py +0 -0
  51. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/instantiate.py +0 -0
  52. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/items.py +0 -0
  53. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/jsonnet2json.py +0 -0
  54. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/object_utilities.py +0 -0
  55. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/property_names.py +0 -0
  56. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/provision.py +0 -0
  57. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/provision_utils.py +0 -0
  58. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/resize.py +0 -0
  59. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/start.py +0 -0
  60. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/start_hold_common.py +0 -0
  61. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/submit.py +0 -0
  62. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/submit_utils.py +0 -0
  63. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/terminate.py +0 -0
  64. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/type_check.py +0 -0
  65. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/upload.py +0 -0
  66. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/upload_utils.py +0 -0
  67. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/utils.py +0 -0
  68. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/validate_properties.py +0 -0
  69. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/variables.py +0 -0
  70. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/version.py +0 -0
  71. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yd_commands/wrapper.py +0 -0
  72. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yellowdog_python_examples.egg-info/SOURCES.txt +0 -0
  73. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yellowdog_python_examples.egg-info/dependency_links.txt +0 -0
  74. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yellowdog_python_examples.egg-info/entry_points.txt +0 -0
  75. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yellowdog_python_examples.egg-info/requires.txt +0 -0
  76. {yellowdog_python_examples-7.8.8 → yellowdog_python_examples-7.9.1}/yellowdog_python_examples.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: yellowdog-python-examples
3
- Version: 7.8.8
3
+ Version: 7.9.1
4
4
  Summary: Example Python commands using the YellowDog Python SDK
5
5
  Home-page: https://github.com/yellowdog/python-examples
6
6
  Author: YellowDog Limited
@@ -43,6 +43,7 @@ The command scripts support:
43
43
 
44
44
  - **Provisioning** Worker Pools with the **`yd-provision`** command
45
45
  - **Submitting** Work Requirements with the **`yd-submit`** command
46
+ - **Starting** HELD Work Requirements and **Holding** (or pausing) RUNNING Work Requirements with the **`yd-start`** and **`yd-hold`** commands
46
47
  - **Uploading** files to the YellowDog Object Store with the **`yd-upload`** command
47
48
  - **Instantiating** Compute Requirements with the **`yd-instantiate`** command
48
49
  - **Downloading** Results from the YellowDog Object Store with the **`yd-download`** command
@@ -52,7 +53,9 @@ The command scripts support:
52
53
  - **Terminating** Compute Requirements with the **`yd-terminate`** command
53
54
  - **Deleting** objects in the YellowDog Object Store with the **`yd-delete`** command
54
55
  - **Listing** YellowDog items using the **`yd-list`** command
55
- - **Resizing** Worker Pools and Compute Requirements
56
- - **Creating, Updating and Removing** Source Templates, Compute Templates, Keyrings, Credentials, Namespace Storage Configurations, Image Families, and Configured Worker Pools
56
+ - **Resizing** Worker Pools and Compute Requirements with the **`yd-resize`** command
57
+ - **Boosting** Allowances with the **`yd-boost`** command
58
+ - **Creating, Updating and Removing** Source Templates, Compute Templates, Keyrings, Credentials, Namespace Storage Configurations, Image Families, Allowances, and Configured Worker Pools with the **`yd-create`** and **`yd-remove`** commands
59
+ - **Following Event Streams** for Work Requirements, Worker Pools and Compute Requirements with the **`yd-follow`** command
57
60
 
58
- Please see the [GitHub repository](https://github.com/yellowdog/python-examples) for more details.
61
+ Please see the documenation in the [GitHub repository](https://github.com/yellowdog/python-examples) for more details.
@@ -8,6 +8,7 @@ The command scripts support:
8
8
 
9
9
  - **Provisioning** Worker Pools with the **`yd-provision`** command
10
10
  - **Submitting** Work Requirements with the **`yd-submit`** command
11
+ - **Starting** HELD Work Requirements and **Holding** (or pausing) RUNNING Work Requirements with the **`yd-start`** and **`yd-hold`** commands
11
12
  - **Uploading** files to the YellowDog Object Store with the **`yd-upload`** command
12
13
  - **Instantiating** Compute Requirements with the **`yd-instantiate`** command
13
14
  - **Downloading** Results from the YellowDog Object Store with the **`yd-download`** command
@@ -17,7 +18,9 @@ The command scripts support:
17
18
  - **Terminating** Compute Requirements with the **`yd-terminate`** command
18
19
  - **Deleting** objects in the YellowDog Object Store with the **`yd-delete`** command
19
20
  - **Listing** YellowDog items using the **`yd-list`** command
20
- - **Resizing** Worker Pools and Compute Requirements
21
- - **Creating, Updating and Removing** Source Templates, Compute Templates, Keyrings, Credentials, Namespace Storage Configurations, Image Families, and Configured Worker Pools
21
+ - **Resizing** Worker Pools and Compute Requirements with the **`yd-resize`** command
22
+ - **Boosting** Allowances with the **`yd-boost`** command
23
+ - **Creating, Updating and Removing** Source Templates, Compute Templates, Keyrings, Credentials, Namespace Storage Configurations, Image Families, Allowances, and Configured Worker Pools with the **`yd-create`** and **`yd-remove`** commands
24
+ - **Following Event Streams** for Work Requirements, Worker Pools and Compute Requirements with the **`yd-follow`** command
22
25
 
23
- Please see the [GitHub repository](https://github.com/yellowdog/python-examples) for more details.
26
+ Please see the documenation in the [GitHub repository](https://github.com/yellowdog/python-examples) for more details.
@@ -87,6 +87,9 @@
87
87
  * [Namespace Storage Configurations](#namespace-storage-configurations)
88
88
  * [Configured Worker Pools](#configured-worker-pools)
89
89
  * [Allowances](#allowances)
90
+ * [Attribute Definitions](#attribute-definitions)
91
+ * [String Attribute Definitions](#string-attribute-definitions)
92
+ * [Numeric Attribute Definitions](#numeric-attribute-definitions)
90
93
  * [Jsonnet Support](#jsonnet-support)
91
94
  * [Jsonnet Installation](#jsonnet-installation)
92
95
  * [Variable Substitutions in Jsonnet Files](#variable-substitutions-in-jsonnet-files)
@@ -114,7 +117,7 @@
114
117
  * [yd-boost](#yd-boost)
115
118
 
116
119
  <!-- Created by https://github.com/ekalinin/github-markdown-toc -->
117
- <!-- Added by: pwt, at: Fri Apr 19 11:43:37 BST 2024 -->
120
+ <!-- Added by: pwt, at: Thu May 9 16:47:20 BST 2024 -->
118
121
 
119
122
  <!--te-->
120
123
 
@@ -156,6 +159,8 @@ Run any command with the `--help`/`-h` option to discover the command's options.
156
159
 
157
160
  # YellowDog Prerequisites
158
161
 
162
+ (See also the quick start guides for [Provisioned](https://github.com/yellowdog/python-examples-templates/blob/main/quickstart.md) and [Configured](https://github.com/yellowdog/python-examples-templates/blob/main/quickstart-configured.md) Worker Pools.)
163
+
159
164
  To submit **Work Requirements** to YellowDog for processing by Configured Worker Pools (on-premise) and/or Provisioned Worker Pools (cloud-provisioned resources), you'll need:
160
165
 
161
166
  1. A YellowDog Platform Account.
@@ -176,7 +181,7 @@ To set up **Configured Worker Pools**, you'll need:
176
181
  5. A Configured Worker Pool Token: from the **Workers** tab in the [YellowDog Portal](https://portal.yellowdog.co/#/workers), use the **+Add Configured Worker Pool** button to create a new Worker Pool and generate a token.
177
182
 
178
183
 
179
- 6. Obtain the YellowDog Agent and install/configure it on your on-premise systems using the Token above.
184
+ 6. Obtain the YellowDog Agent and install/configure it on your on-premise systems using the Token obtained above. See guidance for [Linux](https://github.com/yellowdog/resources/blob/main/agent-install/linux/README.md) and [Windows](https://github.com/yellowdog/resources/blob/main/agent-install/windows/README-CONFIGURED.md).
180
185
 
181
186
  # Script Installation with Pip
182
187
 
@@ -391,21 +396,25 @@ Substitutions can also be performed for non-string (number, boolean, array, and
391
396
 
392
397
  The following substitutions are automatically created and can be used in any section of the configuration file, or in any JSON specification:
393
398
 
394
- | Directive | Description | Example of Substitution |
395
- |:----------------|:-------------------------------------------------------------------------|:------------------------|
396
- | `{{username}}` | The current user's login username, lower case, spaces replaced | jane_smith |
397
- | `{{date}}` | The current date (UTC): YYYYMMDD | 20221027 |
398
- | `{{time}}` | The current time (UTC): HHMMSSss | 16302699 |
399
- | `{{datetime}}` | Concatenation of the date and time, with a '-' separator | 20221027-163026 |
400
- | `{{random}}` | A random, three digit hexadecimal number (lower case) | a1c |
401
- | `{{namespace}}` | The `namespace` property. | my_namespace |
402
- | `{{tag}}` | The `tag` property. | my_tag |
403
- | `{{key}}` | The application `key` property. | |
404
- | `{{secret}}` | The application `secret` property. | |
405
- | `{{url}}` | The Platform `url` property. | |
399
+ | Directive | Description | Example of Substitution |
400
+ |:----------------------|:---------------------------------------------------------------|:------------------------|
401
+ | `{{username}}` | The current user's login username, lower case, spaces replaced | jane_smith |
402
+ | `{{date}}` | The current date (UTC): YYYYMMDD | 20221027 |
403
+ | `{{time}}` | The current time (UTC): HHMMSSss | 16302699 |
404
+ | `{{datetime}}` | Concatenation of the date and time, with a '-' separator | 20221027-163026 |
405
+ | `{{random}}` | A random, three digit hexadecimal number (lower case) | a1c |
406
+ | `{{namespace}}` | The `namespace` property. | my_namespace |
407
+ | `{{tag}}` | The `tag` property. | my_tag |
408
+ | `{{key}}` | The application `key` property. | |
409
+ | `{{secret}}` | The application `secret` property. | |
410
+ | `{{url}}` | The Platform `url` property. | |
411
+ | `{{config_dir_abs}}` | The absolute directory path of the configuration file | /yellowdog/workloads |
412
+ | `{{config_dir_name}}` | The immediate containing directory of the configuration file | workloads |
406
413
 
407
414
  For the `date`, `time`, `datetime` and `random` directives, the same values will be used for the duration of a command -- i.e., if `{{time}}` is used within multiple properties, the identical value will be used for each substitution.
408
415
 
416
+ The `config_dir_` substitutions use the name of the directory containing the nominated TOML configuration file, or the invocation directory if no configuration file is supplied.
417
+
409
418
  ## User-Defined Variables
410
419
 
411
420
  User-defined variables can be supplied using an option on the command line, or by setting environment variables prefixed with `YD_VAR_`, or by including the directives in the `[common]` section of the TOML configuration file.
@@ -413,7 +422,7 @@ User-defined variables can be supplied using an option on the command line, or b
413
422
  1. The **command line** option is `--variable` (or `-v`). For example, `yd-submit -v project_code=pr-213-a -v run_id=1234` will establish two new variables that can be used as `{{project_code}}` and `{{run_id}}`, which will be substituted by `pr-213-a` and `1234` respectively.
414
423
 
415
424
 
416
- 2. For **environment variables**, setting the variable `YD_VAR_project_code="pr-213-a"` will create a new variable that can be used as `{{project_code}}`, which will be substituted by `pr-213-a`.
425
+ 2. For **environment variables**, setting the variable `YD_VAR_project_code="pr-213-a"` will create a new variable that can be used as `{{project_code}}`, which will be substituted by `pr-213-a`. Note that if running on Windows, all environment variable names are case-insensitive and converted to upper case, so choose upper case variable names only.
417
426
 
418
427
 
419
428
  3. For **setting within the TOML file**, include a **`variables`** table in the `[common]` section of the file. E.g., `variables = {project_code = "pr-213a", run_id = "1234"}`. Note that this can also use the form:
@@ -662,7 +671,7 @@ inputs = ["my_bash_script.sh"]
662
671
  arguments = ["{{wr_name}}/my_bash_script.sh", "1", "2", "3"]
663
672
  ```
664
673
 
665
- In the case of Windows batch (`.bat`) files, a `/c` flag is prepended to the `cmd.exe` argument list to ensure correct execution bahaviour. For example:
674
+ In the case of Windows batch (`.bat`) files, a `/c` flag is prepended to the `cmd.exe` argument list to ensure correct execution behaviour. For example:
666
675
 
667
676
  ```toml
668
677
  taskType = "cmd" # or "bat"
@@ -1023,11 +1032,10 @@ A simple example of the JSON output is shown below, showing a Work Requirement w
1023
1032
  `% yd-submit --dry-run --quiet`
1024
1033
  ```json
1025
1034
  {
1026
- "fulfilOnSubmit": false,
1027
- "name": "pyex-bash_230114-095504-53a",
1028
- "namespace": "pyexamples",
1035
+ "name": "pyex-bash-pwt2_240424-12051160",
1036
+ "namespace": "pyexamples-pwt2",
1029
1037
  "priority": 0,
1030
- "tag": "pyex-bash",
1038
+ "tag": "pyex-bash-pwt2",
1031
1039
  "taskGroups": [
1032
1040
  {
1033
1041
  "finishIfAllTasksFinished": true,
@@ -1035,22 +1043,33 @@ A simple example of the JSON output is shown below, showing a Work Requirement w
1035
1043
  "name": "task_group_1",
1036
1044
  "priority": 0,
1037
1045
  "runSpecification": {
1038
- "maximumTaskRetries": 0,
1046
+ "maximumTaskRetries": 5,
1039
1047
  "taskTypes": ["bash"],
1040
- "workerTags": ["pyex-bash"]
1048
+ "workerTags": ["pyex-bash-pwt2-worker", "onpremise-pwt2"]
1041
1049
  },
1050
+ "starved": false,
1051
+ "waitingOnDependency": false,
1042
1052
  "tasks": [
1043
1053
  {
1044
- "arguments": ["pyex-bash_230114-095504-53a/sleep_script.sh"],
1045
- "environment": {},
1054
+ "arguments": ["pyex-bash-pwt2_240424-12051160/sleep_script.sh", 1, 2, 3],
1055
+ "environment": {
1056
+ "TEST_ENV_1": "100",
1057
+ "TEST_ENV_2": "200",
1058
+ "YD_TASK_NAME": "task_1",
1059
+ "YD_TASK_NUMBER": "1",
1060
+ "YD_TASK_GROUP_NAME": "task_group_1",
1061
+ "YD_TASK_GROUP_NUMBER": "1",
1062
+ "YD_WORK_REQUIREMENT_NAME": "pyex-bash-pwt2_240424-12051160",
1063
+ "YD_NAMESPACE": "pyexamples-pwt2"
1064
+ },
1046
1065
  "inputs": [
1047
1066
  {
1048
- "objectNamePattern": "pyex-bash_230114-095504-53a/sleep_script.sh",
1067
+ "objectNamePattern": "pyex-bash-pwt2_240424-12051160/sleep_script.sh",
1049
1068
  "source": "TASK_NAMESPACE",
1050
- "verification": "VERIFY_WAIT"
1069
+ "verification": "VERIFY_AT_START"
1051
1070
  }
1052
1071
  ],
1053
- "name": "task_01",
1072
+ "name": "task_1",
1054
1073
  "outputs": [
1055
1074
  {"alwaysUpload": true, "required": false, "source": "PROCESS_OUTPUT"}
1056
1075
  ],
@@ -1587,13 +1606,13 @@ Here's an example of the `workerPool` section of a TOML configuration file, show
1587
1606
  templateId = "ydid:crt:D9C548:465a107c-7cea-46e3-9fdd-15116cb92c40"
1588
1607
  # Note: only one of 'userData'/'userDataFile'/'userDataFiles' should be set
1589
1608
  userData = ""
1590
- userDataFile = "myuserdata.txt"
1591
- userDataFiles = ["myuserdata1.txt", "myuserdata2.txt"]
1609
+ # userDataFile = "myuserdata.txt"
1610
+ # userDataFiles = ["myuserdata1.txt", "myuserdata2.txt"]
1592
1611
  workerTag = "tag-{{username}}"
1593
1612
  # Specify either workersPerNode or workersPerVCPU
1594
1613
  workersPerNode = 1
1595
- workersPerVCPU = 1
1596
- # workerPoolData = "worker_pool.json"
1614
+ # workersPerVCPU = 1
1615
+ # workerPoolData = "worker_pool.json" # Optionally specify worker pool JSON specification
1597
1616
  ```
1598
1617
 
1599
1618
  ## Worker Pool Specification Using JSON Documents
@@ -1782,6 +1801,7 @@ The commands **yd-create** and **yd-remove** allow the creation, update and remo
1782
1801
  - Namespace Storage Configurations
1783
1802
  - Configured Worker Pools
1784
1803
  - Allowances
1804
+ - String Attribute Definitions
1785
1805
 
1786
1806
  ## Overview of Operation
1787
1807
 
@@ -2145,6 +2165,44 @@ When using `yd-remove`, Allowances are again matched using their `description` p
2145
2165
 
2146
2166
  Allowances can be **boosted** (have extra hours added to the Allowance) using the `yd-boost` command.
2147
2167
 
2168
+ ## Attribute Definitions
2169
+
2170
+ The Attribute Definition example and schema can be found at: https://docs.yellowdog.co/api/?spec=Compute%20API#tag/compute/post/compute/attributes/user.
2171
+
2172
+ ### String Attribute Definitions
2173
+
2174
+ Example:
2175
+
2176
+ ```json
2177
+ {
2178
+ "resource": "StringAttributeDefinition",
2179
+ "name": "user.my-attribute",
2180
+ "title": "My attribute title",
2181
+ "description": "This is a description of my attribute",
2182
+ "options": ["yes", "no", "maybe"]
2183
+ }
2184
+ ```
2185
+
2186
+ The `name` and `title` properties are required, while the rest are optional. The `user.` prefix is required when specifying the `name` property.
2187
+
2188
+ ### Numeric Attribute Definitions
2189
+
2190
+ Example:
2191
+
2192
+ ```json
2193
+ {
2194
+ "resource": "NumericAttributeDefinition",
2195
+ "name": "my-numeric-attribute",
2196
+ "title": "Attribute Title",
2197
+ "defaultRankOrder": "PREFER_LOWER",
2198
+ "description": "A description of the attribute",
2199
+ "units": "$",
2200
+ "range": {"min": 1, "max": 10}
2201
+ }
2202
+ ```
2203
+
2204
+ The `name`, `title` and `defaultRankOrder` properties are required, while the rest are optional. The `user.` prefix is required when specifying the `name` property.
2205
+
2148
2206
  # Jsonnet Support
2149
2207
 
2150
2208
  In all circumstances where JSON files are used by the Python Examples commands, **[Jsonnet](https://jsonnet.org)** files can be used instead. This allows the use of Jsonnet's powerful JSON extensions, including comments, variables, functions, etc.
@@ -0,0 +1 @@
1
+ __version__ = "7.9.1"
@@ -529,6 +529,13 @@ class CLIParser:
529
529
  required=False,
530
530
  help="list allowances",
531
531
  )
532
+ parser.add_argument(
533
+ "--attribute-definitions",
534
+ "-R",
535
+ action="store_true",
536
+ required=False,
537
+ help="list attribute definitions",
538
+ )
532
539
 
533
540
  if any(module in sys.argv[0] for module in ["upload"]):
534
541
  parser.add_argument(
@@ -1310,6 +1317,11 @@ class CLIParser:
1310
1317
  def allowances(self) -> Optional[bool]:
1311
1318
  return self.args.allowances
1312
1319
 
1320
+ @property
1321
+ @allow_missing_attribute
1322
+ def attribute_definitions(self) -> Optional[bool]:
1323
+ return self.args.attribute_definitions
1324
+
1313
1325
  @property
1314
1326
  @allow_missing_attribute
1315
1327
  def show_keyring_passwords(self) -> Optional[bool]:
@@ -10,7 +10,7 @@ from typing import Dict, List, Optional
10
10
 
11
11
  import yellowdog_client.model as model
12
12
  from dateparser import parse as date_parse
13
- from requests import post
13
+ from requests import post, put
14
14
  from requests.exceptions import HTTPError
15
15
  from yellowdog_client.model import (
16
16
  AccountAllowance,
@@ -51,9 +51,11 @@ from yd_commands.settings import (
51
51
  RN_CREDENTIAL,
52
52
  RN_IMAGE_FAMILY,
53
53
  RN_KEYRING,
54
+ RN_NUMERIC_ATTRIBUTE_DEFINITION,
54
55
  RN_REQUIREMENT_TEMPLATE,
55
56
  RN_SOURCE_TEMPLATE,
56
57
  RN_STORAGE_CONFIGURATION,
58
+ RN_STRING_ATTRIBUTE_DEFINITION,
57
59
  )
58
60
  from yd_commands.wrapper import ARGS_PARSER, CLIENT, CONFIG_COMMON, main_wrapper
59
61
 
@@ -118,6 +120,11 @@ def create_resources(
118
120
  create_configured_worker_pool(resource)
119
121
  elif resource_type == RN_ALLOWANCE:
120
122
  create_allowance(resource)
123
+ elif resource_type in [
124
+ RN_STRING_ATTRIBUTE_DEFINITION,
125
+ RN_NUMERIC_ATTRIBUTE_DEFINITION,
126
+ ]:
127
+ create_attribute_definition_via_api(resource, resource_type)
121
128
  else:
122
129
  print_error(f"Unknown resource type '{resource_type}'")
123
130
  except Exception as e:
@@ -789,6 +796,59 @@ def _get_model_class(class_name: str):
789
796
  return getattr(model, class_name)
790
797
 
791
798
 
799
+ def create_attribute_definition_via_api(resource: Dict, resource_type: str):
800
+ """
801
+ Use the API to create/update user attribute definitions.
802
+ """
803
+ try:
804
+ name = resource["name"]
805
+ title = resource["title"]
806
+ if resource_type == RN_NUMERIC_ATTRIBUTE_DEFINITION:
807
+ default_rank_order = resource["defaultRankOrder"]
808
+ except KeyError as e:
809
+ raise Exception(f"Expected property to be defined ({e})")
810
+
811
+ url = f"{CONFIG_COMMON.url}/compute/attributes/user"
812
+ headers = {"Authorization": f"yd-key {CONFIG_COMMON.key}:{CONFIG_COMMON.secret}"}
813
+ if resource_type == RN_STRING_ATTRIBUTE_DEFINITION:
814
+ payload = {
815
+ "type": "co.yellowdog.platform.model.StringAttributeDefinition",
816
+ "name": name,
817
+ "title": title,
818
+ "description": resource.get("description"),
819
+ "options": resource.get("options"),
820
+ }
821
+ else: # RN_NUMERIC_ATTRIBUTE_DEFINITION
822
+ payload = {
823
+ "type": "co.yellowdog.platform.model.NumericAttributeDefinition",
824
+ "name": name,
825
+ "title": title,
826
+ "defaultRankOrder": default_rank_order,
827
+ "description": resource.get("description"),
828
+ "units": resource.get("units"),
829
+ "range": resource.get("range"),
830
+ }
831
+
832
+ # Attempt attribute creation
833
+ print_log(f"Attempting to create or update Attribute Definition '{name}'")
834
+ response = post(url=url, headers=headers, json=payload)
835
+
836
+ if response.status_code == 200:
837
+ print_log(f"Created new Attribute Definition '{name}'")
838
+ return
839
+
840
+ if "Attribute already exists" in response.text:
841
+ if not confirmed(f"Update existing Attribute Definition '{name}'?"):
842
+ return
843
+
844
+ response = put(url=url, headers=headers, json=payload)
845
+ if response.status_code == 200:
846
+ print_log(f"Updated existing Attribute Definition '{name}'")
847
+ return
848
+
849
+ raise Exception(f"HTTP {response.status_code} ({response.text})")
850
+
851
+
792
852
  # Entry point
793
853
  if __name__ == "__main__":
794
854
  main()
@@ -3,7 +3,7 @@ User interaction processing utilities.
3
3
  """
4
4
 
5
5
  from os import getenv
6
- from typing import List, Optional, Set, Union
6
+ from typing import Dict, List, Optional, Set, Union
7
7
 
8
8
  from yellowdog_client import PlatformClient
9
9
 
@@ -30,13 +30,14 @@ YD_YES = "YD_YES"
30
30
 
31
31
  def select(
32
32
  client: PlatformClient,
33
- objects: List[Union[Item, str]],
33
+ objects: List[Union[Item, str, Dict]],
34
34
  object_type_name: Optional[str] = None,
35
35
  override_quiet: bool = False,
36
36
  single_result: bool = False,
37
37
  showing_all: bool = False,
38
38
  force_interactive: bool = False,
39
39
  result_required: bool = False,
40
+ sort_objects: bool = True,
40
41
  ) -> List[Item]:
41
42
  """
42
43
  Print a numbered list of objects.
@@ -47,7 +48,8 @@ def select(
47
48
  if len(objects) == 0:
48
49
  return objects
49
50
 
50
- objects = sorted_objects(objects)
51
+ if sort_objects:
52
+ objects = sorted_objects(objects)
51
53
 
52
54
  if not ARGS_PARSER.quiet or override_quiet or ARGS_PARSER.interactive:
53
55
  print_numbered_object_list(
@@ -5,6 +5,7 @@ Command to list YellowDog entities.
5
5
  """
6
6
 
7
7
  from dataclasses import asdict, fields
8
+ from json import loads as json_loads
8
9
  from typing import Dict, List
9
10
 
10
11
  from requests import get
@@ -47,6 +48,7 @@ from yd_commands.object_utilities import (
47
48
  )
48
49
  from yd_commands.printing import (
49
50
  indent,
51
+ print_json,
50
52
  print_log,
51
53
  print_numbered_object_list,
52
54
  print_table_core,
@@ -85,6 +87,8 @@ def main():
85
87
  list_namespaces()
86
88
  elif ARGS_PARSER.allowances:
87
89
  list_allowances()
90
+ elif ARGS_PARSER.attribute_definitions:
91
+ list_attribute_definitions()
88
92
 
89
93
 
90
94
  def check_for_valid_option() -> bool:
@@ -105,6 +109,7 @@ def check_for_valid_option() -> bool:
105
109
  ARGS_PARSER.namespace_storage_configurations,
106
110
  ARGS_PARSER.instances,
107
111
  ARGS_PARSER.allowances,
112
+ ARGS_PARSER.attribute_definitions,
108
113
  ].count(True) == 1:
109
114
  return True
110
115
  else:
@@ -568,6 +573,39 @@ def list_allowances():
568
573
  print_yd_object(allowance)
569
574
 
570
575
 
576
+ def list_attribute_definitions():
577
+ """
578
+ List user compute attribute definitions using the API.
579
+ """
580
+ response = get(
581
+ url=f"{CONFIG_COMMON.url}/compute/attributes/user",
582
+ headers={"Authorization": f"yd-key {CONFIG_COMMON.key}:{CONFIG_COMMON.secret}"},
583
+ )
584
+
585
+ if response.status_code != 200:
586
+ raise Exception(
587
+ "Unable to list user attribute definitions: HTTP "
588
+ f"{response.status_code} ({response.text})"
589
+ )
590
+
591
+ attribute_definition_list = json_loads(response.text)
592
+ attribute_definition_list.sort(key=lambda x: x["name"])
593
+
594
+ if not ARGS_PARSER.details:
595
+ print_numbered_object_list(
596
+ CLIENT, attribute_definition_list, object_type_name="Attribute Definition"
597
+ )
598
+ return
599
+
600
+ for selected_attribute_definition in select(
601
+ CLIENT,
602
+ attribute_definition_list,
603
+ object_type_name="Attribute Definition",
604
+ sort_objects=False,
605
+ ):
606
+ print_json(selected_attribute_definition)
607
+
608
+
571
609
  # Entry point
572
610
  if __name__ == "__main__":
573
611
  main()
@@ -4,7 +4,8 @@ Common utility functions, mostly related to loading configuration data.
4
4
 
5
5
  import os
6
6
  from os import getenv
7
- from os.path import dirname, join, relpath
7
+ from os.path import abspath, dirname, join, relpath
8
+ from pathlib import Path
8
9
  from sys import exit
9
10
  from typing import Dict, Optional
10
11
 
@@ -49,6 +50,11 @@ CONFIG_FILE = relpath(
49
50
 
50
51
  try:
51
52
  CONFIG_FILE_DIR = dirname(CONFIG_FILE)
53
+ config_dir_abs = abspath(CONFIG_FILE_DIR)
54
+ config_dir_short = Path(config_dir_abs).parts[-1]
55
+ VARIABLE_SUBSTITUTIONS.update(
56
+ {"config_dir_abs": config_dir_abs, "config_dir_name": config_dir_short}
57
+ )
52
58
  print_log(f"Loading configuration data from: '{CONFIG_FILE}'")
53
59
  CONFIG_TOML: Dict = load_toml_file_with_variable_substitutions(CONFIG_FILE)
54
60
  try:
@@ -13,9 +13,11 @@ from yd_commands.settings import (
13
13
  RN_CREDENTIAL,
14
14
  RN_IMAGE_FAMILY,
15
15
  RN_KEYRING,
16
+ RN_NUMERIC_ATTRIBUTE_DEFINITION,
16
17
  RN_REQUIREMENT_TEMPLATE,
17
18
  RN_SOURCE_TEMPLATE,
18
19
  RN_STORAGE_CONFIGURATION,
20
+ RN_STRING_ATTRIBUTE_DEFINITION,
19
21
  )
20
22
  from yd_commands.variables import (
21
23
  load_json_file_with_variable_substitutions,
@@ -94,6 +96,8 @@ def _resequence_resources(
94
96
  RN_KEYRING,
95
97
  RN_CREDENTIAL,
96
98
  RN_IMAGE_FAMILY,
99
+ RN_STRING_ATTRIBUTE_DEFINITION,
100
+ RN_NUMERIC_ATTRIBUTE_DEFINITION,
97
101
  RN_SOURCE_TEMPLATE,
98
102
  RN_REQUIREMENT_TEMPLATE,
99
103
  RN_ALLOWANCE,
@@ -552,6 +552,30 @@ def allowances_table(
552
552
  return headers, table
553
553
 
554
554
 
555
+ def attribute_definitions_table(
556
+ attribute_definitions: List[Dict],
557
+ ) -> (List[str], List[str]):
558
+ headers = [
559
+ "#",
560
+ "Name",
561
+ "Type",
562
+ "Title",
563
+ "Description",
564
+ ]
565
+ table = []
566
+ for index, attribute_definition in enumerate(attribute_definitions):
567
+ table.append(
568
+ [
569
+ index + 1,
570
+ attribute_definition["name"],
571
+ attribute_definition["type"].split(".")[-1],
572
+ attribute_definition["title"],
573
+ attribute_definition.get("description", ""),
574
+ ]
575
+ )
576
+ return headers, table
577
+
578
+
555
579
  def aws_availability_zone_table(
556
580
  aws_azs: List[AWSAvailabilityZone],
557
581
  ) -> (List[str], List[str]):
@@ -576,7 +600,7 @@ def aws_availability_zone_table(
576
600
 
577
601
  def print_numbered_object_list(
578
602
  client: PlatformClient,
579
- objects: List[Union[Item, str]],
603
+ objects: List[Union[Item, str, Dict]],
580
604
  object_type_name: Optional[str] = None,
581
605
  override_quiet: bool = False,
582
606
  showing_all: bool = False,
@@ -626,6 +650,8 @@ def print_numbered_object_list(
626
650
  headers, table = allowances_table(objects)
627
651
  elif isinstance(objects[0], AWSAvailabilityZone):
628
652
  headers, table = aws_availability_zone_table(objects)
653
+ elif object_type_name == "Attribute Definition":
654
+ headers, table = attribute_definitions_table(objects)
629
655
  else:
630
656
  table = []
631
657
  for index, obj in enumerate(objects):
@@ -7,6 +7,7 @@ A script to remove YellowDog resources.
7
7
  from copy import deepcopy
8
8
  from typing import Dict, List, Optional
9
9
 
10
+ from requests import delete
10
11
  from requests.exceptions import HTTPError
11
12
  from yellowdog_client.model import (
12
13
  MachineImage,
@@ -31,11 +32,13 @@ from yd_commands.settings import (
31
32
  RN_CREDENTIAL,
32
33
  RN_IMAGE_FAMILY,
33
34
  RN_KEYRING,
35
+ RN_NUMERIC_ATTRIBUTE_DEFINITION,
34
36
  RN_REQUIREMENT_TEMPLATE,
35
37
  RN_SOURCE_TEMPLATE,
36
38
  RN_STORAGE_CONFIGURATION,
39
+ RN_STRING_ATTRIBUTE_DEFINITION,
37
40
  )
38
- from yd_commands.wrapper import ARGS_PARSER, CLIENT, main_wrapper
41
+ from yd_commands.wrapper import ARGS_PARSER, CLIENT, CONFIG_COMMON, main_wrapper
39
42
 
40
43
 
41
44
  @main_wrapper
@@ -92,6 +95,11 @@ def remove_resources(resources: Optional[List[Dict]] = None):
92
95
  "alternatively, Allowances can be removed by their "
93
96
  "YellowDog IDs (yd-remove --ids)"
94
97
  )
98
+ elif resource_type in [
99
+ RN_STRING_ATTRIBUTE_DEFINITION,
100
+ RN_NUMERIC_ATTRIBUTE_DEFINITION,
101
+ ]:
102
+ remove_attribute_definition_via_api(resource)
95
103
  else:
96
104
  print_error(f"Unknown resource type '{resource_type}'")
97
105
  except Exception as e:
@@ -407,6 +415,29 @@ def remove_resource_by_id(resource_id: str):
407
415
  print_error(f"Unable to remove resource with ID {resource_id}: {e}")
408
416
 
409
417
 
418
+ def remove_attribute_definition_via_api(resource: Dict):
419
+ """
420
+ Use the API to remove user string attribute definitions.
421
+ """
422
+ try:
423
+ name = resource["name"]
424
+ except KeyError as e:
425
+ raise Exception(f"Expected property to be defined ({e})")
426
+
427
+ if not confirmed(f"Remove Attribute Definition '{name}'?"):
428
+ return
429
+
430
+ url = f"{CONFIG_COMMON.url}/compute/attributes/user/{name}"
431
+ headers = {"Authorization": f"yd-key {CONFIG_COMMON.key}:{CONFIG_COMMON.secret}"}
432
+ response = delete(url=url, headers=headers)
433
+
434
+ if response.status_code == 200:
435
+ print_log(f"Removed Attribute Definition '{name}' (if present)")
436
+ return
437
+
438
+ raise Exception(f"HTTP {response.status_code} ({response.text})")
439
+
440
+
410
441
  # Entry point
411
442
  if __name__ == "__main__":
412
443
  main()
@@ -105,3 +105,5 @@ RN_KEYRING = "Keyring"
105
105
  RN_REQUIREMENT_TEMPLATE = "ComputeRequirementTemplate"
106
106
  RN_SOURCE_TEMPLATE = "ComputeSourceTemplate"
107
107
  RN_STORAGE_CONFIGURATION = "NamespaceStorageConfiguration"
108
+ RN_STRING_ATTRIBUTE_DEFINITION = "StringAttributeDefinition"
109
+ RN_NUMERIC_ATTRIBUTE_DEFINITION = "NumericAttributeDefinition"
@@ -32,9 +32,11 @@ def main():
32
32
  return
33
33
 
34
34
  print_log(
35
- "Shutting down Worker Pools with Compute Requirements in "
35
+ "Shutting down Provisioned Worker Pools with Compute Requirements in "
36
36
  f"namespace '{CONFIG_COMMON.namespace}' and "
37
- f"tag starting with '{CONFIG_COMMON.name_tag}'"
37
+ f"tag starting with '{CONFIG_COMMON.name_tag}' "
38
+ "(or Configured Worker Pools with names starting with "
39
+ f"'{CONFIG_COMMON.name_tag}')"
38
40
  )
39
41
  worker_pool_summaries: List[WorkerPoolSummary] = (
40
42
  CLIENT.worker_pool_client.find_all_worker_pools()
@@ -43,11 +45,19 @@ def main():
43
45
 
44
46
  selected_worker_pool_summaries: List[WorkerPoolSummary] = []
45
47
  for worker_pool_summary in worker_pool_summaries:
46
- if not (
47
- "ProvisionedWorkerPool" not in worker_pool_summary.type
48
- or worker_pool_summary.status
49
- in [WorkerPoolStatus.TERMINATED, WorkerPoolStatus.SHUTDOWN]
50
- ):
48
+ if worker_pool_summary.status not in [
49
+ WorkerPoolStatus.TERMINATED,
50
+ WorkerPoolStatus.SHUTDOWN,
51
+ ]:
52
+ if "ProvisionedWorkerPool" not in worker_pool_summary.type:
53
+ # Configured Worker Pool: check worker pool name only
54
+ if (
55
+ worker_pool_summary.name is not None
56
+ and worker_pool_summary.name.startswith(CONFIG_COMMON.name_tag)
57
+ ):
58
+ selected_worker_pool_summaries.append(worker_pool_summary)
59
+ continue
60
+
51
61
  worker_pool: WorkerPool = get_worker_pool_by_id(
52
62
  CLIENT, worker_pool_summary.id
53
63
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: yellowdog-python-examples
3
- Version: 7.8.8
3
+ Version: 7.9.1
4
4
  Summary: Example Python commands using the YellowDog Python SDK
5
5
  Home-page: https://github.com/yellowdog/python-examples
6
6
  Author: YellowDog Limited
@@ -43,6 +43,7 @@ The command scripts support:
43
43
 
44
44
  - **Provisioning** Worker Pools with the **`yd-provision`** command
45
45
  - **Submitting** Work Requirements with the **`yd-submit`** command
46
+ - **Starting** HELD Work Requirements and **Holding** (or pausing) RUNNING Work Requirements with the **`yd-start`** and **`yd-hold`** commands
46
47
  - **Uploading** files to the YellowDog Object Store with the **`yd-upload`** command
47
48
  - **Instantiating** Compute Requirements with the **`yd-instantiate`** command
48
49
  - **Downloading** Results from the YellowDog Object Store with the **`yd-download`** command
@@ -52,7 +53,9 @@ The command scripts support:
52
53
  - **Terminating** Compute Requirements with the **`yd-terminate`** command
53
54
  - **Deleting** objects in the YellowDog Object Store with the **`yd-delete`** command
54
55
  - **Listing** YellowDog items using the **`yd-list`** command
55
- - **Resizing** Worker Pools and Compute Requirements
56
- - **Creating, Updating and Removing** Source Templates, Compute Templates, Keyrings, Credentials, Namespace Storage Configurations, Image Families, and Configured Worker Pools
56
+ - **Resizing** Worker Pools and Compute Requirements with the **`yd-resize`** command
57
+ - **Boosting** Allowances with the **`yd-boost`** command
58
+ - **Creating, Updating and Removing** Source Templates, Compute Templates, Keyrings, Credentials, Namespace Storage Configurations, Image Families, Allowances, and Configured Worker Pools with the **`yd-create`** and **`yd-remove`** commands
59
+ - **Following Event Streams** for Work Requirements, Worker Pools and Compute Requirements with the **`yd-follow`** command
57
60
 
58
- Please see the [GitHub repository](https://github.com/yellowdog/python-examples) for more details.
61
+ Please see the documenation in the [GitHub repository](https://github.com/yellowdog/python-examples) for more details.
@@ -1 +0,0 @@
1
- __version__ = "7.8.8"