yellowdog-python-examples 7.20.3__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.3/yellowdog_python_examples.egg-info → yellowdog_python_examples-8.0.0}/PKG-INFO +2 -2
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/README.md +20 -5
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/requirements.txt +1 -1
- {yellowdog_python_examples-7.20.3 → 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.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/create.py +159 -49
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/list.py +14 -7
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/entity_utils.py +10 -5
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/settings.py +4 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0/yellowdog_python_examples.egg-info}/PKG-INFO +2 -2
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_python_examples.egg-info/requires.txt +1 -1
- yellowdog_python_examples-7.20.3/yellowdog_cli/__init__.py +0 -1
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/LICENSE +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/PYPI_README.md +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/pyproject.toml +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/setup.cfg +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/tests/test_create_remove.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/tests/test_demos.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/tests/test_dryruns.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/tests/test_entrypoints.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/tests/test_gui.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/tests/test_objects.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/tests/test_variable_processing.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/abort.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/admin.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/boost.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/cancel.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/cloudwizard.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/compare.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/delete.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/download.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/follow.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/format_json.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/hold.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/instantiate.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/jsonnet2json.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/provision.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/remove.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/resize.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/show.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/shutdown.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/start.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/submit.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/terminate.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/upload.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/__init__.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/args.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/check_imports.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/cloudwizard_aws.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/cloudwizard_aws_types.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/cloudwizard_azure.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/cloudwizard_common.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/cloudwizard_gcp.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/compact_json.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/config_types.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/csv_data.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/follow_utils.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/interactive.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/items.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/load_config.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/load_resources.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/misc_utils.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/printing.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/property_names.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/provision_utils.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/rich_console_input_fixed.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/start_hold_common.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/submit_utils.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/type_check.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/upload_utils.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/validate_properties.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/variables.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/wrapper.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/ydid_utils.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/version.py +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_python_examples.egg-info/SOURCES.txt +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_python_examples.egg-info/dependency_links.txt +0 -0
- {yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_python_examples.egg-info/entry_points.txt +0 -0
- {yellowdog_python_examples-7.20.3 → 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
|
|
@@ -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.3 → 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
|
)
|
|
@@ -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
|
|
{yellowdog_python_examples-7.20.3 → 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.3"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.3 → 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.3 → 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.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/cancel.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/cloudwizard.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/compare.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/delete.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/download.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/follow.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/format_json.py
RENAMED
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/instantiate.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/jsonnet2json.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/provision.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/remove.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/resize.py
RENAMED
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/shutdown.py
RENAMED
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/submit.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/terminate.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/upload.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/__init__.py
RENAMED
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/args.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.3 → 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.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/items.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.3 → 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.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/utils/wrapper.py
RENAMED
|
File without changes
|
|
File without changes
|
{yellowdog_python_examples-7.20.3 → yellowdog_python_examples-8.0.0}/yellowdog_cli/version.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|