yellowdog-python-examples 7.20.2__tar.gz → 8.0.0__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.
- {yellowdog_python_examples-7.20.2/yellowdog_python_examples.egg-info → yellowdog_python_examples-8.0.0}/PKG-INFO +2 -2
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/README.md +25 -10
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/requirements.txt +1 -1
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/tests/test_list.py +12 -0
- yellowdog_python_examples-8.0.0/yellowdog_cli/__init__.py +1 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/create.py +159 -49
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/list.py +14 -7
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/args.py +12 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/entity_utils.py +10 -5
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/load_config.py +44 -34
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/settings.py +4 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0/yellowdog_python_examples.egg-info}/PKG-INFO +2 -2
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_python_examples.egg-info/requires.txt +1 -1
- yellowdog_python_examples-7.20.2/yellowdog_cli/__init__.py +0 -1
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/LICENSE +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/PYPI_README.md +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/pyproject.toml +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/setup.cfg +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/tests/test_create_remove.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/tests/test_demos.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/tests/test_dryruns.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/tests/test_entrypoints.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/tests/test_gui.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/tests/test_objects.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/tests/test_variable_processing.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/abort.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/admin.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/boost.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/cancel.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/cloudwizard.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/compare.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/delete.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/download.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/follow.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/format_json.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/hold.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/instantiate.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/jsonnet2json.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/provision.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/remove.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/resize.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/show.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/shutdown.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/start.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/submit.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/terminate.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/upload.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/__init__.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/check_imports.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/cloudwizard_aws.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/cloudwizard_aws_types.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/cloudwizard_azure.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/cloudwizard_common.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/cloudwizard_gcp.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/compact_json.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/config_types.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/csv_data.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/follow_utils.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/interactive.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/items.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/load_resources.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/misc_utils.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/printing.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/property_names.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/provision_utils.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/rich_console_input_fixed.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/start_hold_common.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/submit_utils.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/type_check.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/upload_utils.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/validate_properties.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/variables.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/wrapper.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/ydid_utils.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/version.py +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_python_examples.egg-info/SOURCES.txt +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_python_examples.egg-info/dependency_links.txt +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_python_examples.egg-info/entry_points.txt +0 -0
- {yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/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:
|
|
3
|
+
Version: 8.0.0
|
|
4
4
|
Summary: Python CLI commands using the YellowDog Python SDK
|
|
5
5
|
Author-email: YellowDog Limited <support@yellowdog.co>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -26,7 +26,7 @@ Requires-Dist: requests
|
|
|
26
26
|
Requires-Dist: rich==13.9.4
|
|
27
27
|
Requires-Dist: tabulate>=0.9.0
|
|
28
28
|
Requires-Dist: toml
|
|
29
|
-
Requires-Dist: yellowdog-sdk>=11.2.
|
|
29
|
+
Requires-Dist: yellowdog-sdk>=11.2.1
|
|
30
30
|
Provides-Extra: jsonnet
|
|
31
31
|
Requires-Dist: jsonnet; extra == "jsonnet"
|
|
32
32
|
Provides-Extra: cloudwizard
|
|
@@ -395,7 +395,7 @@ The **environment variables** are as follows:
|
|
|
395
395
|
- `YD_NAMESPACE`
|
|
396
396
|
- `YD_TAG`
|
|
397
397
|
|
|
398
|
-
When setting the value of the above properties, a property set on the command line takes precedence over one set via
|
|
398
|
+
When setting the value of the above properties, a property set on the command line takes precedence over one set via the configuration file, and both take precedence over a value set in an environment variable.
|
|
399
399
|
|
|
400
400
|
If all the required common properties are set using the command line or environment variables, then the entire `common` section of the TOML file can be omitted.
|
|
401
401
|
|
|
@@ -486,10 +486,10 @@ User-defined variable names must not include spaces, but are otherwise unconstra
|
|
|
486
486
|
The precedence order for setting variables is:
|
|
487
487
|
|
|
488
488
|
1. Command line
|
|
489
|
-
2.
|
|
490
|
-
3.
|
|
491
|
-
4.
|
|
492
|
-
5.
|
|
489
|
+
2. TOML configuration file
|
|
490
|
+
3. `YD_VAR` environment variables
|
|
491
|
+
4. General environment variables
|
|
492
|
+
5. Variables in a `.env` file
|
|
493
493
|
|
|
494
494
|
This method can also be used to override the default variables, e.g., setting `-v username="other-user"` will override the default `{{username}}` variable.
|
|
495
495
|
|
|
@@ -2427,16 +2427,31 @@ Namespace Policies are matched by their `namespace` property when using `yd-crea
|
|
|
2427
2427
|
|
|
2428
2428
|
## Groups
|
|
2429
2429
|
|
|
2430
|
-
When creating and updating groups, a list of roles can can be supplied and the group will be created or updated with the roles specified. Roles can be identified by their names or YellowDog IDs.
|
|
2430
|
+
When creating and updating groups, a list of roles with their scopes can can be supplied and the group will be created or updated with the roles specified. Roles can be identified by their names or YellowDog IDs.
|
|
2431
2431
|
|
|
2432
2432
|
Example:
|
|
2433
2433
|
|
|
2434
2434
|
```json
|
|
2435
2435
|
{
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2436
|
+
"resource": "Group",
|
|
2437
|
+
"name": "my-group",
|
|
2438
|
+
"description": "Description of my group",
|
|
2439
|
+
"roles": [
|
|
2440
|
+
{
|
|
2441
|
+
"role": {"name": "work-viewer"},
|
|
2442
|
+
"scope": {"global": true}
|
|
2443
|
+
},
|
|
2444
|
+
{
|
|
2445
|
+
"role": {"name": "work-manager"},
|
|
2446
|
+
"scope": {
|
|
2447
|
+
"global": false,
|
|
2448
|
+
"namespaces": [
|
|
2449
|
+
{"namespace": "namespace-1"},
|
|
2450
|
+
{"namespace": "namespace-2"}
|
|
2451
|
+
]
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
]
|
|
2440
2455
|
}
|
|
2441
2456
|
```
|
|
2442
2457
|
|
|
@@ -57,3 +57,15 @@ class TestList:
|
|
|
57
57
|
def test_allowances(self):
|
|
58
58
|
result = shell("yd-list -A -n='' -t=''")
|
|
59
59
|
assert result.exit_code == 0
|
|
60
|
+
|
|
61
|
+
def test_groups(self):
|
|
62
|
+
result = shell("yd-list --groups -n='' -t=''")
|
|
63
|
+
assert result.exit_code == 0
|
|
64
|
+
|
|
65
|
+
def test_roles(self):
|
|
66
|
+
result = shell("yd-list --roles -n='' -t=''")
|
|
67
|
+
assert result.exit_code == 0
|
|
68
|
+
|
|
69
|
+
def test_permissions(self):
|
|
70
|
+
result = shell("yd-list --permissions -n='' -t=''")
|
|
71
|
+
assert result.exit_code == 0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "8.0.0"
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/create.py
RENAMED
|
@@ -5,8 +5,9 @@ A script to create or update YellowDog resources.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from copy import deepcopy
|
|
8
|
+
from dataclasses import dataclass
|
|
8
9
|
from datetime import datetime
|
|
9
|
-
from typing import Dict, List, Optional
|
|
10
|
+
from typing import Dict, List, Optional, Set
|
|
10
11
|
|
|
11
12
|
import yellowdog_client.model as model
|
|
12
13
|
from dateparser import parse as date_parse
|
|
@@ -16,6 +17,7 @@ from yellowdog_client.model import (
|
|
|
16
17
|
AccountAllowance,
|
|
17
18
|
AddApplicationResponse,
|
|
18
19
|
AddConfiguredWorkerPoolResponse,
|
|
20
|
+
AddGroupRequest,
|
|
19
21
|
AllowanceLimitEnforcement,
|
|
20
22
|
AllowanceResetType,
|
|
21
23
|
ApiKey,
|
|
@@ -25,6 +27,7 @@ from yellowdog_client.model import (
|
|
|
25
27
|
CloudProvider,
|
|
26
28
|
CreateNamespaceRequest,
|
|
27
29
|
Group,
|
|
30
|
+
GroupRole,
|
|
28
31
|
ImageOsType,
|
|
29
32
|
InstanceStatus,
|
|
30
33
|
InternalUser,
|
|
@@ -38,6 +41,7 @@ from yellowdog_client.model import (
|
|
|
38
41
|
RoleScope,
|
|
39
42
|
SourceAllowance,
|
|
40
43
|
SourcesAllowance,
|
|
44
|
+
UpdateGroupRequest,
|
|
41
45
|
User,
|
|
42
46
|
)
|
|
43
47
|
from yellowdog_client.model.exceptions import InvalidRequestException
|
|
@@ -78,6 +82,7 @@ from yellowdog_cli.utils.settings import (
|
|
|
78
82
|
PROP_DESCRIPTION,
|
|
79
83
|
PROP_EFFECTIVE_FROM,
|
|
80
84
|
PROP_EFFECTIVE_UNTIL,
|
|
85
|
+
PROP_GLOBAL,
|
|
81
86
|
PROP_GROUPS,
|
|
82
87
|
PROP_ID,
|
|
83
88
|
PROP_IMAGE,
|
|
@@ -86,12 +91,15 @@ from yellowdog_cli.utils.settings import (
|
|
|
86
91
|
PROP_KEYRING_NAME,
|
|
87
92
|
PROP_NAME,
|
|
88
93
|
PROP_NAMESPACE,
|
|
94
|
+
PROP_NAMESPACES,
|
|
89
95
|
PROP_OPTIONS,
|
|
90
96
|
PROP_OS_TYPE,
|
|
91
97
|
PROP_RANGE,
|
|
92
98
|
PROP_REQUIREMENT_CREATED_FROM,
|
|
93
99
|
PROP_RESOURCE,
|
|
100
|
+
PROP_ROLE,
|
|
94
101
|
PROP_ROLES,
|
|
102
|
+
PROP_SCOPE,
|
|
95
103
|
PROP_SOURCE,
|
|
96
104
|
PROP_SOURCE_CREATED_FROM,
|
|
97
105
|
PROP_SOURCES,
|
|
@@ -100,7 +108,6 @@ from yellowdog_cli.utils.settings import (
|
|
|
100
108
|
PROP_UNITS,
|
|
101
109
|
PROP_USERNAME,
|
|
102
110
|
RN_ADD_APPLICATION_REQUEST,
|
|
103
|
-
RN_ADD_GROUP_REQUEST,
|
|
104
111
|
RN_ALLOWANCE,
|
|
105
112
|
RN_APPLICATION,
|
|
106
113
|
RN_CONFIGURED_POOL,
|
|
@@ -118,7 +125,6 @@ from yellowdog_cli.utils.settings import (
|
|
|
118
125
|
RN_STORAGE_CONFIGURATION,
|
|
119
126
|
RN_STRING_ATTRIBUTE_DEFINITION,
|
|
120
127
|
RN_UPDATE_APPLICATION_REQUEST,
|
|
121
|
-
RN_UPDATE_GROUP_REQUEST,
|
|
122
128
|
)
|
|
123
129
|
from yellowdog_cli.utils.wrapper import ARGS_PARSER, CLIENT, CONFIG_COMMON, main_wrapper
|
|
124
130
|
from yellowdog_cli.utils.ydid_utils import YDIDType, get_ydid_type
|
|
@@ -938,69 +944,171 @@ def create_namespace_policy(resource: Dict):
|
|
|
938
944
|
)
|
|
939
945
|
|
|
940
946
|
|
|
947
|
+
@dataclass
|
|
948
|
+
class RoleSpecification:
|
|
949
|
+
"""
|
|
950
|
+
Class to represent a compact expression of a role.
|
|
951
|
+
"""
|
|
952
|
+
|
|
953
|
+
id: str
|
|
954
|
+
name: str
|
|
955
|
+
global_: Optional[bool]
|
|
956
|
+
namespaces: Optional[Set[str]]
|
|
957
|
+
|
|
958
|
+
|
|
941
959
|
def create_group(resource: Dict):
|
|
942
960
|
"""
|
|
943
|
-
Create or update a group. Will also add or remove
|
|
944
|
-
by their names or IDs.
|
|
961
|
+
Create or update a group. Will also add or remove scoped
|
|
962
|
+
roles specified by their names or IDs.
|
|
945
963
|
"""
|
|
946
964
|
try:
|
|
947
965
|
name = resource[PROP_NAME]
|
|
966
|
+
description = resource.get(PROP_DESCRIPTION)
|
|
948
967
|
except KeyError as e:
|
|
949
968
|
raise Exception(f"Expected property to be defined ({e})")
|
|
950
969
|
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
if roles is not None:
|
|
954
|
-
# Convert role names to IDs
|
|
955
|
-
new_role_ids = set()
|
|
956
|
-
for role_name in roles:
|
|
957
|
-
role_id = get_role_id_by_name(CLIENT, role_name)
|
|
958
|
-
if role_id is None:
|
|
959
|
-
print_warning(f"Role '{role_name}' not found ... ignoring")
|
|
960
|
-
else:
|
|
961
|
-
new_role_ids.add(role_id)
|
|
962
|
-
|
|
963
|
-
def update_roles(group: Group):
|
|
970
|
+
def get_updated_role_specifications() -> List[RoleSpecification]:
|
|
964
971
|
"""
|
|
965
|
-
Helper function to
|
|
972
|
+
Helper function to generate the list of supplied role specifications.
|
|
966
973
|
"""
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
974
|
+
roles_input = resource.get(PROP_ROLES)
|
|
975
|
+
if roles_input is None:
|
|
976
|
+
return []
|
|
977
|
+
|
|
978
|
+
role_specifications = []
|
|
979
|
+
for role_item in roles_input:
|
|
980
|
+
# Get the role
|
|
981
|
+
role = role_item.get(PROP_ROLE)
|
|
982
|
+
if role is None:
|
|
983
|
+
raise Exception("Role must have 'role' property")
|
|
984
|
+
|
|
985
|
+
# Get the ID and name of the role
|
|
986
|
+
id_ = role.get(PROP_ID)
|
|
987
|
+
if id_ is None:
|
|
988
|
+
name_ = role.get(PROP_NAME)
|
|
989
|
+
if name_ is None:
|
|
990
|
+
raise Exception("Group role must have 'id' or 'name' specified")
|
|
991
|
+
id_ = get_role_id_by_name(CLIENT, name_)
|
|
992
|
+
else:
|
|
993
|
+
name_ = role.get(PROP_NAME)
|
|
994
|
+
if name_ is None:
|
|
995
|
+
name_ = get_role_name_by_id(CLIENT, id_)
|
|
996
|
+
|
|
997
|
+
# Get the scope of the role
|
|
998
|
+
scope = role_item.get(PROP_SCOPE)
|
|
999
|
+
if scope is None:
|
|
1000
|
+
raise Exception(f"Group role '{name_}' must have 'scope' specified")
|
|
1001
|
+
global_ = scope.get(PROP_GLOBAL)
|
|
1002
|
+
if global_ is None or global_ is False:
|
|
1003
|
+
namespaces_ = scope.get(PROP_NAMESPACES)
|
|
1004
|
+
if namespaces_ is None:
|
|
1005
|
+
raise Exception(
|
|
1006
|
+
f"Non-global group role '{name_}' must have 'namespaces' specified"
|
|
1007
|
+
)
|
|
1008
|
+
namespace_names = []
|
|
1009
|
+
for namespace_ in namespaces_:
|
|
1010
|
+
namespace_name = namespace_.get(PROP_NAMESPACE)
|
|
1011
|
+
if namespace_name is None:
|
|
1012
|
+
raise Exception(
|
|
1013
|
+
f"Namespace applied to role '{name_}' "
|
|
1014
|
+
"must have 'namespace' property"
|
|
1015
|
+
)
|
|
1016
|
+
namespace_names.append(namespace_name)
|
|
1017
|
+
|
|
1018
|
+
# Construct the role specification & add to the list
|
|
1019
|
+
if len(namespace_names) == 0:
|
|
1020
|
+
raise Exception(
|
|
1021
|
+
f"Non-global role '{name_}' must have at least one namespace scope"
|
|
1022
|
+
)
|
|
1023
|
+
role_specifications.append(
|
|
1024
|
+
RoleSpecification(
|
|
1025
|
+
id=id_,
|
|
1026
|
+
name=name_,
|
|
1027
|
+
global_=False,
|
|
1028
|
+
namespaces=set(namespace_names),
|
|
1029
|
+
)
|
|
1030
|
+
)
|
|
1031
|
+
else:
|
|
1032
|
+
role_specifications.append(
|
|
1033
|
+
RoleSpecification(id=id_, name=name_, global_=True, namespaces=None)
|
|
1034
|
+
)
|
|
971
1035
|
|
|
972
|
-
|
|
973
|
-
print_log("No Role additions or deletions required")
|
|
974
|
-
return
|
|
1036
|
+
return role_specifications
|
|
975
1037
|
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1038
|
+
def add_or_update_roles(role_specifications: List[RoleSpecification]):
|
|
1039
|
+
"""
|
|
1040
|
+
Helper function to add/update a list of roles.
|
|
1041
|
+
"""
|
|
1042
|
+
for role_spec in role_specifications:
|
|
1043
|
+
CLIENT.account_client.add_role_to_group(
|
|
1044
|
+
group_id,
|
|
1045
|
+
role_spec.id,
|
|
1046
|
+
RoleScope(role_spec.global_, role_spec.namespaces),
|
|
982
1047
|
)
|
|
1048
|
+
if role_spec.global_:
|
|
1049
|
+
print_log(f"Added/updated role '{role_spec.name}' with global scope")
|
|
1050
|
+
else:
|
|
1051
|
+
ns_list_quoted = [f"'{ns}'" for ns in role_spec.namespaces]
|
|
1052
|
+
print_log(
|
|
1053
|
+
f"Added/updated role '{role_spec.name}' scoped to "
|
|
1054
|
+
f"namespace(s): {', '.join(ns_list_quoted)}"
|
|
1055
|
+
)
|
|
983
1056
|
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
1057
|
+
def remove_roles(role_specifications: List[RoleSpecification]):
|
|
1058
|
+
"""
|
|
1059
|
+
Helper function to remove a list of roles.
|
|
1060
|
+
"""
|
|
1061
|
+
for role_spec in role_specifications:
|
|
1062
|
+
CLIENT.account_client.remove_role_from_group(
|
|
1063
|
+
group_id,
|
|
1064
|
+
role_spec.id,
|
|
988
1065
|
)
|
|
989
|
-
|
|
990
|
-
f"
|
|
991
|
-
|
|
1066
|
+
if role_spec.global_:
|
|
1067
|
+
print_log(f"Removed role '{role_spec.name}' with global scope")
|
|
1068
|
+
else:
|
|
1069
|
+
ns_list_quoted = [f"'{ns}'" for ns in role_spec.namespaces]
|
|
1070
|
+
print_log(
|
|
1071
|
+
f"Removed role '{role_spec.name}' scoped to "
|
|
1072
|
+
f"namespace(s): {', '.join(ns_list_quoted)}"
|
|
1073
|
+
)
|
|
1074
|
+
|
|
1075
|
+
def get_roles_to_remove(
|
|
1076
|
+
existing_roles: List[GroupRole], new_roles: List[RoleSpecification]
|
|
1077
|
+
) -> List[RoleSpecification]:
|
|
1078
|
+
"""
|
|
1079
|
+
Helper function to determine the roles to be removed.
|
|
1080
|
+
"""
|
|
1081
|
+
existing_role_specifications = [
|
|
1082
|
+
RoleSpecification(
|
|
1083
|
+
id=role.role.id,
|
|
1084
|
+
name=role.role.name,
|
|
1085
|
+
global_=role.scope.global_,
|
|
1086
|
+
namespaces=(
|
|
1087
|
+
None
|
|
1088
|
+
if role.scope.namespaces is None
|
|
1089
|
+
else set([ns.namespace for ns in role.scope.namespaces])
|
|
1090
|
+
),
|
|
992
1091
|
)
|
|
1092
|
+
for role in existing_roles
|
|
1093
|
+
]
|
|
1094
|
+
# Select roles to remove
|
|
1095
|
+
return [
|
|
1096
|
+
role_spec
|
|
1097
|
+
for role_spec in existing_role_specifications
|
|
1098
|
+
if role_spec.name not in [role_spec.name for role_spec in new_roles]
|
|
1099
|
+
]
|
|
993
1100
|
|
|
994
|
-
def add_group():
|
|
1101
|
+
def add_group() -> str:
|
|
995
1102
|
"""
|
|
996
|
-
Helper function to add a new group
|
|
1103
|
+
Helper function to add a new group.
|
|
1104
|
+
Return the ID of the newly created group.
|
|
997
1105
|
"""
|
|
998
1106
|
group: Group = CLIENT.account_client.add_group(
|
|
999
|
-
|
|
1107
|
+
AddGroupRequest(name=name, description=description)
|
|
1000
1108
|
)
|
|
1001
1109
|
print_log(f"Created Group '{group.name}' ({group.id})")
|
|
1002
1110
|
clear_group_caches()
|
|
1003
|
-
|
|
1111
|
+
return group.id
|
|
1004
1112
|
|
|
1005
1113
|
def update_group(group_id: str):
|
|
1006
1114
|
"""
|
|
@@ -1009,18 +1117,20 @@ def create_group(resource: Dict):
|
|
|
1009
1117
|
"""
|
|
1010
1118
|
if not confirmed(f"Update Group '{name}' ({group_id})?"):
|
|
1011
1119
|
return
|
|
1012
|
-
|
|
1013
1120
|
group: Group = CLIENT.account_client.update_group(
|
|
1014
|
-
group_id,
|
|
1121
|
+
group_id, UpdateGroupRequest(name=name, description=description)
|
|
1015
1122
|
)
|
|
1016
1123
|
print_log(f"Updated Group '{group.name}' ({group.id})")
|
|
1017
|
-
|
|
1124
|
+
updated_role_specs = get_updated_role_specifications()
|
|
1125
|
+
remove_roles(get_roles_to_remove(group.roles, updated_role_specs))
|
|
1126
|
+
add_or_update_roles(updated_role_specs)
|
|
1018
1127
|
|
|
1019
1128
|
# Main logic
|
|
1020
1129
|
group_id = get_group_id_by_name(CLIENT, name)
|
|
1021
|
-
if group_id is None:
|
|
1022
|
-
add_group()
|
|
1023
|
-
|
|
1130
|
+
if group_id is None: # New group
|
|
1131
|
+
group_id = add_group()
|
|
1132
|
+
add_or_update_roles(get_updated_role_specifications())
|
|
1133
|
+
else: # Existing group
|
|
1024
1134
|
update_group(group_id)
|
|
1025
1135
|
|
|
1026
1136
|
|
|
@@ -62,6 +62,7 @@ from yellowdog_cli.utils.entity_utils import (
|
|
|
62
62
|
get_user_groups,
|
|
63
63
|
get_worker_pools,
|
|
64
64
|
list_matching_object_paths,
|
|
65
|
+
substitute_id_for_name_in_allowance,
|
|
65
66
|
substitute_ids_for_names_in_crt,
|
|
66
67
|
substitute_image_family_id_for_name_in_cst,
|
|
67
68
|
)
|
|
@@ -807,14 +808,26 @@ def list_allowances():
|
|
|
807
808
|
print_log("No Allowances to display")
|
|
808
809
|
return
|
|
809
810
|
|
|
811
|
+
if ARGS_PARSER.ids_only:
|
|
812
|
+
for allowance in allowances:
|
|
813
|
+
print(allowance.id)
|
|
814
|
+
return
|
|
815
|
+
|
|
810
816
|
if not ARGS_PARSER.details:
|
|
811
817
|
print_numbered_object_list(CLIENT, allowances)
|
|
812
818
|
return
|
|
813
819
|
|
|
814
820
|
# Show details
|
|
821
|
+
if len(allowances) > 0 and ARGS_PARSER.substitute_ids:
|
|
822
|
+
print_log(
|
|
823
|
+
"Substituting Compute Requirement Template IDs with names (if applicable)"
|
|
824
|
+
)
|
|
815
825
|
print_yd_object_list(
|
|
816
826
|
[
|
|
817
|
-
(
|
|
827
|
+
(
|
|
828
|
+
substitute_id_for_name_in_allowance(CLIENT, allowance),
|
|
829
|
+
{PROP_RESOURCE: RN_ALLOWANCE},
|
|
830
|
+
)
|
|
818
831
|
for allowance in select(CLIENT, allowances)
|
|
819
832
|
]
|
|
820
833
|
)
|
|
@@ -1010,12 +1023,6 @@ def list_groups():
|
|
|
1010
1023
|
|
|
1011
1024
|
selected_groups = select(CLIENT, groups)
|
|
1012
1025
|
|
|
1013
|
-
# If stripping IDs, just supply the list of role names;
|
|
1014
|
-
# subverts the type
|
|
1015
|
-
if ARGS_PARSER.strip_ids:
|
|
1016
|
-
for group in selected_groups:
|
|
1017
|
-
group.roles = [group_role.role.name for group_role in group.roles]
|
|
1018
|
-
|
|
1019
1026
|
print_yd_object_list(
|
|
1020
1027
|
[(group, {PROP_RESOURCE: RN_GROUP}) for group in selected_groups]
|
|
1021
1028
|
)
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/args.py
RENAMED
|
@@ -127,6 +127,13 @@ class CLIParser:
|
|
|
127
127
|
required=False,
|
|
128
128
|
help="include the process ID of this CLI invocation alongside timestamp in logging messages",
|
|
129
129
|
)
|
|
130
|
+
parser.add_argument(
|
|
131
|
+
"--no-config",
|
|
132
|
+
"--nc",
|
|
133
|
+
action="store_true",
|
|
134
|
+
required=False,
|
|
135
|
+
help="ignore the contents of any TOML configuration file (even if specified on the command line)",
|
|
136
|
+
)
|
|
130
137
|
|
|
131
138
|
# Module-specific argument sets
|
|
132
139
|
if not any(module in sys.argv[0] for module in ["compare"]):
|
|
@@ -1287,6 +1294,11 @@ class CLIParser:
|
|
|
1287
1294
|
def print_pid(self) -> Optional[bool]:
|
|
1288
1295
|
return self.args.print_pid
|
|
1289
1296
|
|
|
1297
|
+
@property
|
|
1298
|
+
@allow_missing_attribute
|
|
1299
|
+
def no_config(self) -> Optional[bool]:
|
|
1300
|
+
return self.args.no_config
|
|
1301
|
+
|
|
1290
1302
|
@property
|
|
1291
1303
|
@allow_missing_attribute
|
|
1292
1304
|
def work_req_file(self) -> Optional[str]:
|
|
@@ -8,6 +8,7 @@ from typing import Callable, List, Optional, Tuple, Union
|
|
|
8
8
|
from yellowdog_client import PlatformClient
|
|
9
9
|
from yellowdog_client.common import SearchClient
|
|
10
10
|
from yellowdog_client.model import (
|
|
11
|
+
AccountAllowance,
|
|
11
12
|
AllowanceSearch,
|
|
12
13
|
Application,
|
|
13
14
|
ApplicationSearch,
|
|
@@ -635,11 +636,17 @@ def substitute_image_family_id_for_name_in_cst(
|
|
|
635
636
|
|
|
636
637
|
def substitute_id_for_name_in_allowance(
|
|
637
638
|
client: PlatformClient,
|
|
638
|
-
allowance: Union[
|
|
639
|
-
|
|
639
|
+
allowance: Union[
|
|
640
|
+
AccountAllowance, RequirementsAllowance, SourcesAllowance, SourceAllowance
|
|
641
|
+
],
|
|
642
|
+
) -> Union[AccountAllowance, RequirementsAllowance, SourcesAllowance, SourceAllowance]:
|
|
640
643
|
"""
|
|
641
644
|
Substitute IDs in Allowance objects.
|
|
642
645
|
"""
|
|
646
|
+
|
|
647
|
+
if not ARGS_PARSER.substitute_ids:
|
|
648
|
+
return allowance
|
|
649
|
+
|
|
643
650
|
if isinstance(allowance, RequirementsAllowance):
|
|
644
651
|
allowance.requirementCreatedFromId = _get_requirement_template_name_from_id(
|
|
645
652
|
client, allowance.requirementCreatedFromId
|
|
@@ -650,9 +657,7 @@ def substitute_id_for_name_in_allowance(
|
|
|
650
657
|
client, allowance.sourceCreatedFromId
|
|
651
658
|
)
|
|
652
659
|
|
|
653
|
-
|
|
654
|
-
# No processing for source allowances
|
|
655
|
-
pass
|
|
660
|
+
# No processing for other allowance types
|
|
656
661
|
|
|
657
662
|
return allowance
|
|
658
663
|
|
|
@@ -59,7 +59,6 @@ for norm, alt in [
|
|
|
59
59
|
]:
|
|
60
60
|
if os.getenv(norm) is None and os.getenv(alt) is not None:
|
|
61
61
|
os.environ[norm] = os.getenv(alt)
|
|
62
|
-
print_log(f"Setting environment variable '{norm}' using value of '{alt}'")
|
|
63
62
|
|
|
64
63
|
# CLI > YD_CONF > 'config.toml'
|
|
65
64
|
CONFIG_FILE = relpath(
|
|
@@ -68,42 +67,50 @@ CONFIG_FILE = relpath(
|
|
|
68
67
|
else ARGS_PARSER.config_file
|
|
69
68
|
)
|
|
70
69
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
CONFIG_TOML: Dict = load_toml_file_with_variable_substitutions(CONFIG_FILE)
|
|
70
|
+
if ARGS_PARSER.no_config:
|
|
71
|
+
# Suppress use of any TOML config file
|
|
72
|
+
print_log(f"Configuration file ('{CONFIG_FILE}') ignored")
|
|
73
|
+
CONFIG_TOML = {COMMON_SECTION: {}}
|
|
74
|
+
CONFIG_FILE_DIR = os.getcwd()
|
|
75
|
+
|
|
76
|
+
else:
|
|
77
|
+
# Attempt to load configuration data from TOML file
|
|
80
78
|
try:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
CONFIG_FILE_DIR = dirname(CONFIG_FILE)
|
|
80
|
+
config_dir_abs = abspath(CONFIG_FILE_DIR)
|
|
81
|
+
config_dir_short = Path(config_dir_abs).parts[-1]
|
|
82
|
+
VARIABLE_SUBSTITUTIONS.update(
|
|
83
|
+
{"config_dir_abs": config_dir_abs, "config_dir_name": config_dir_short}
|
|
84
|
+
)
|
|
85
|
+
print_log(f"Loading configuration data from: '{CONFIG_FILE}'")
|
|
86
|
+
CONFIG_TOML: Dict = load_toml_file_with_variable_substitutions(CONFIG_FILE)
|
|
87
|
+
try:
|
|
88
|
+
validate_properties(CONFIG_TOML, f"'{CONFIG_FILE}'")
|
|
89
|
+
except Exception as e:
|
|
90
|
+
print_error(e)
|
|
91
|
+
exit(1)
|
|
92
|
+
|
|
93
|
+
except FileNotFoundError as e:
|
|
94
|
+
if ARGS_PARSER.config_file is not None:
|
|
95
|
+
print_error(e)
|
|
96
|
+
exit(1)
|
|
97
|
+
# No config file, so create a stub config dictionary
|
|
98
|
+
print_log(
|
|
99
|
+
"No configuration file; expecting configuration data on command line "
|
|
100
|
+
"or in environment variables"
|
|
101
|
+
)
|
|
102
|
+
CONFIG_TOML = {COMMON_SECTION: {}}
|
|
103
|
+
CONFIG_FILE_DIR = os.getcwd()
|
|
104
|
+
|
|
105
|
+
except (PermissionError, TomlDecodeError) as e:
|
|
106
|
+
print_error(
|
|
107
|
+
f"Unable to load configuration data from '{CONFIG_FILE}': {e}",
|
|
108
|
+
)
|
|
84
109
|
exit(1)
|
|
85
110
|
|
|
86
|
-
except
|
|
87
|
-
if ARGS_PARSER.config_file is not None:
|
|
111
|
+
except Exception as e:
|
|
88
112
|
print_error(e)
|
|
89
113
|
exit(1)
|
|
90
|
-
# No config file, so create a stub config dictionary
|
|
91
|
-
print_log(
|
|
92
|
-
"No configuration file; expecting configuration data on command line "
|
|
93
|
-
"or in environment variables"
|
|
94
|
-
)
|
|
95
|
-
CONFIG_TOML = {COMMON_SECTION: {}}
|
|
96
|
-
CONFIG_FILE_DIR = os.getcwd()
|
|
97
|
-
|
|
98
|
-
except (PermissionError, TomlDecodeError) as e:
|
|
99
|
-
print_error(
|
|
100
|
-
f"Unable to load configuration data from '{CONFIG_FILE}': {e}",
|
|
101
|
-
)
|
|
102
|
-
exit(1)
|
|
103
|
-
|
|
104
|
-
except Exception as e:
|
|
105
|
-
print_error(e)
|
|
106
|
-
exit(1)
|
|
107
114
|
|
|
108
115
|
|
|
109
116
|
def load_config_common() -> ConfigCommon:
|
|
@@ -123,7 +130,7 @@ def load_config_common() -> ConfigCommon:
|
|
|
123
130
|
|
|
124
131
|
# Replace common section properties with command line or
|
|
125
132
|
# environment variable overrides. Precedence is:
|
|
126
|
-
# command line >
|
|
133
|
+
# command line > config file > environment variable
|
|
127
134
|
for key_name, args_parser_value, env_var_name in [
|
|
128
135
|
(KEY, ARGS_PARSER.key, YD_KEY),
|
|
129
136
|
(SECRET, ARGS_PARSER.secret, YD_SECRET),
|
|
@@ -137,7 +144,10 @@ def load_config_common() -> ConfigCommon:
|
|
|
137
144
|
f"Using '{key_name}' provided on command line "
|
|
138
145
|
"(or automatically set)"
|
|
139
146
|
)
|
|
140
|
-
elif
|
|
147
|
+
elif (
|
|
148
|
+
common_section.get(key_name, None) is None
|
|
149
|
+
and os.environ.get(env_var_name, None) is not None
|
|
150
|
+
):
|
|
141
151
|
common_section[key_name] = os.environ[env_var_name]
|
|
142
152
|
print_log(f"Using '{key_name}' provided via the environment")
|
|
143
153
|
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/settings.py
RENAMED
|
@@ -154,6 +154,7 @@ PROP_DELETABLE = "deletable"
|
|
|
154
154
|
PROP_DESCRIPTION = "description"
|
|
155
155
|
PROP_EFFECTIVE_FROM = "effectiveFrom"
|
|
156
156
|
PROP_EFFECTIVE_UNTIL = "effectiveUntil"
|
|
157
|
+
PROP_GLOBAL = "global"
|
|
157
158
|
PROP_GROUPS = "groups"
|
|
158
159
|
PROP_ID = "id"
|
|
159
160
|
PROP_IMAGE = "image"
|
|
@@ -164,13 +165,16 @@ PROP_KEYRING = "keyring"
|
|
|
164
165
|
PROP_KEYRING_NAME = "keyringName"
|
|
165
166
|
PROP_NAME = "name"
|
|
166
167
|
PROP_NAMESPACE = "namespace"
|
|
168
|
+
PROP_NAMESPACES = "namespaces"
|
|
167
169
|
PROP_OPTIONS = "options"
|
|
168
170
|
PROP_OS_TYPE = "osType"
|
|
169
171
|
PROP_RANGE = "range"
|
|
170
172
|
PROP_REMAINING_HOURS = "remainingHours"
|
|
171
173
|
PROP_REQUIREMENT_CREATED_FROM = "requirementCreatedFromId"
|
|
172
174
|
PROP_RESOURCE = "resource"
|
|
175
|
+
PROP_ROLE = "role"
|
|
173
176
|
PROP_ROLES = "roles"
|
|
177
|
+
PROP_SCOPE = "scope"
|
|
174
178
|
PROP_SOURCE = "source"
|
|
175
179
|
PROP_SOURCES = "sources"
|
|
176
180
|
PROP_SOURCE_CREATED_FROM = "sourceCreatedFromId"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: yellowdog-python-examples
|
|
3
|
-
Version:
|
|
3
|
+
Version: 8.0.0
|
|
4
4
|
Summary: Python CLI commands using the YellowDog Python SDK
|
|
5
5
|
Author-email: YellowDog Limited <support@yellowdog.co>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -26,7 +26,7 @@ Requires-Dist: requests
|
|
|
26
26
|
Requires-Dist: rich==13.9.4
|
|
27
27
|
Requires-Dist: tabulate>=0.9.0
|
|
28
28
|
Requires-Dist: toml
|
|
29
|
-
Requires-Dist: yellowdog-sdk>=11.2.
|
|
29
|
+
Requires-Dist: yellowdog-sdk>=11.2.1
|
|
30
30
|
Provides-Extra: jsonnet
|
|
31
31
|
Requires-Dist: jsonnet; extra == "jsonnet"
|
|
32
32
|
Provides-Extra: cloudwizard
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "7.20.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/tests/test_create_remove.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/tests/test_entrypoints.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/cancel.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/cloudwizard.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/compare.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/delete.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/download.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/follow.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/format_json.py
RENAMED
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/instantiate.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/jsonnet2json.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/provision.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/remove.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/resize.py
RENAMED
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/shutdown.py
RENAMED
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/submit.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/terminate.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/upload.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/csv_data.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/items.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/printing.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/wrapper.py
RENAMED
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.2 → yellowdog_python_examples-8.0.0}/yellowdog_cli/version.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|