azureml-registry-tools 0.1.0a14__py3-none-any.whl → 0.1.0a16__py3-none-any.whl
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.
- azureml/registry/_cli/registry_syndication_cli.py +31 -50
- azureml/registry/data/description.md.template +1 -2
- azureml/registry/data/evaluation.md.template +1 -2
- azureml/registry/data/model.schema.json +2 -1
- azureml/registry/data/notes.md.template +2 -3
- azureml/registry/data/validate_model_schema.py +72 -47
- azureml/registry/mgmt/asset_management.py +58 -70
- {azureml_registry_tools-0.1.0a14.dist-info → azureml_registry_tools-0.1.0a16.dist-info}/METADATA +1 -1
- {azureml_registry_tools-0.1.0a14.dist-info → azureml_registry_tools-0.1.0a16.dist-info}/RECORD +13 -14
- azureml/registry/mgmt/registry_config.py +0 -147
- {azureml_registry_tools-0.1.0a14.dist-info → azureml_registry_tools-0.1.0a16.dist-info}/WHEEL +0 -0
- {azureml_registry_tools-0.1.0a14.dist-info → azureml_registry_tools-0.1.0a16.dist-info}/entry_points.txt +0 -0
- {azureml_registry_tools-0.1.0a14.dist-info → azureml_registry_tools-0.1.0a16.dist-info}/licenses/LICENSE.txt +0 -0
- {azureml_registry_tools-0.1.0a14.dist-info → azureml_registry_tools-0.1.0a16.dist-info}/top_level.txt +0 -0
@@ -15,7 +15,6 @@ from azureml.registry.mgmt.create_manifest import generate_syndication_manifest
|
|
15
15
|
from azureml.registry.mgmt.model_management import (
|
16
16
|
model_delete, model_get, model_list, parse_asset_id
|
17
17
|
)
|
18
|
-
from azureml.registry.mgmt.registry_config import create_registry_config
|
19
18
|
from azureml.registry.mgmt.syndication_manifest import ResyncAssetsInManifestDto, SyndicationManifest
|
20
19
|
|
21
20
|
|
@@ -141,14 +140,6 @@ def show_command(registry_name: str, as_arm_object: bool) -> object:
|
|
141
140
|
return discovery
|
142
141
|
|
143
142
|
|
144
|
-
def validate_registry_cfg(cfg_file_name) -> str:
|
145
|
-
"""Validate if registry config extension is .cfg."""
|
146
|
-
cfg_file_path = Path(cfg_file_name)
|
147
|
-
if not cfg_file_path.suffix == ".cfg":
|
148
|
-
raise argparse.ArgumentTypeError(f"--config arg {cfg_file_name} must be a path to a .cfg file")
|
149
|
-
return cfg_file_path
|
150
|
-
|
151
|
-
|
152
143
|
def _add_common_args(p, arg_dicts=None):
|
153
144
|
if arg_dicts is None:
|
154
145
|
arg_dicts = []
|
@@ -187,14 +178,11 @@ def main() -> None:
|
|
187
178
|
# Validate an asset
|
188
179
|
registry-mgmt asset validate --asset-path ./path-to-asset
|
189
180
|
|
190
|
-
#
|
191
|
-
registry-mgmt asset
|
181
|
+
# Preview an asset to registry
|
182
|
+
registry-mgmt asset preview --asset-path ./path-to-asset --registry-name myreg --subscription sub123 --resource-group rg123
|
192
183
|
|
193
|
-
#
|
194
|
-
registry-mgmt asset
|
195
|
-
|
196
|
-
# Create registry configuration file with storage overrides
|
197
|
-
registry-mgmt asset config --registry-name myreg --subscription sub123 --resource-group rg123 --tenant-id tenant123 --storage-name storage123 --container-name container123 --container-path path123
|
184
|
+
# Deploy an asset to registry
|
185
|
+
registry-mgmt asset deploy --asset-path ./path-to-asset --registry-name myreg --subscription sub123 --resource-group rg123
|
198
186
|
|
199
187
|
# Create asset template files
|
200
188
|
registry-mgmt asset template --folder ./folder-path
|
@@ -352,21 +340,19 @@ def main() -> None:
|
|
352
340
|
asset_validate_parser.add_argument("--asset-path", type=Path, help="Path to the asset folder to validate.")
|
353
341
|
asset_validate_parser.add_argument("--allow-additional-properties", action="store_true",
|
354
342
|
help="Allow additional properties not defined in the schema")
|
343
|
+
# asset preview command
|
344
|
+
asset_preview_parser = asset_subparsers.add_parser("preview", help="Preview a model card to registry.")
|
345
|
+
_add_common_args(asset_preview_parser, [registry_name_arg, subscription_arg, resource_group_arg, dry_run_arg])
|
346
|
+
asset_preview_parser.add_argument("--asset-path", type=Path, help="Path to the asset folder to preview.")
|
347
|
+
asset_preview_parser.add_argument("--allow-additional-properties", action="store_true",
|
348
|
+
help="Allow additional properties not defined in the schema")
|
355
349
|
|
356
350
|
# asset deploy command
|
357
|
-
asset_deploy_parser = asset_subparsers.add_parser("deploy", help="Deploy
|
358
|
-
_add_common_args(asset_deploy_parser, [dry_run_arg])
|
359
|
-
asset_deploy_parser.add_argument("-c", "--config", type=validate_registry_cfg, required=True, help="Path to registry config file.")
|
351
|
+
asset_deploy_parser = asset_subparsers.add_parser("deploy", help="Deploy a model to registry.")
|
352
|
+
_add_common_args(asset_deploy_parser, [registry_name_arg, subscription_arg, resource_group_arg, dry_run_arg])
|
360
353
|
asset_deploy_parser.add_argument("--asset-path", type=Path, help="Path to the asset folder to deploy.")
|
361
|
-
|
362
|
-
|
363
|
-
asset_config_parser = asset_subparsers.add_parser("config", help="Create registry configuration file.")
|
364
|
-
_add_common_args(asset_config_parser, [registry_name_arg, subscription_arg, resource_group_arg])
|
365
|
-
asset_config_parser.add_argument("--tenant-id", type=str, required=True, help="Registry Tenant ID.")
|
366
|
-
asset_config_parser.add_argument("-c", "--config-file", type=validate_registry_cfg, help="Registry config file path to write to (default: registry-mgmt.cfg).")
|
367
|
-
asset_config_parser.add_argument("--storage-name", type=str, help="Storage account name for storage overrides.")
|
368
|
-
asset_config_parser.add_argument("--container-name", type=str, help="Container name for storage overrides.")
|
369
|
-
asset_config_parser.add_argument("--container-path", type=str, help="Container path for storage overrides.")
|
354
|
+
asset_deploy_parser.add_argument("--allow-additional-properties", action="store_true",
|
355
|
+
help="Allow additional properties not defined in the schema")
|
370
356
|
|
371
357
|
# asset template command
|
372
358
|
asset_template_parser = asset_subparsers.add_parser("template", help="Create asset template files.")
|
@@ -448,27 +434,23 @@ def main() -> None:
|
|
448
434
|
syndication_target_set(args.registry_name, args.value, args.dry_run)
|
449
435
|
elif args.command == "asset":
|
450
436
|
if args.asset_subcommand == "validate":
|
451
|
-
# Config file is not needed for validation
|
452
437
|
asset_validate(args.asset_path, args.dry_run, args.allow_additional_properties)
|
438
|
+
elif args.asset_subcommand == "preview":
|
439
|
+
asset_deploy(asset_path=args.asset_path,
|
440
|
+
registry_name=args.registry_name,
|
441
|
+
subscription_id=args.subscription,
|
442
|
+
resource_group=args.resource_group,
|
443
|
+
dry_run=args.dry_run,
|
444
|
+
allow_additional_properties=args.allow_additional_properties,
|
445
|
+
override_storage=True)
|
453
446
|
elif args.asset_subcommand == "deploy":
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
create_registry_config(
|
463
|
-
registry_name=args.registry_name,
|
464
|
-
subscription_id=args.subscription,
|
465
|
-
resource_group=args.resource_group,
|
466
|
-
tenant_id=args.tenant_id,
|
467
|
-
config_file_path=args.config_file,
|
468
|
-
storage_name=args.storage_name,
|
469
|
-
container_name=args.container_name,
|
470
|
-
container_path=args.container_path
|
471
|
-
)
|
447
|
+
asset_deploy(asset_path=args.asset_path,
|
448
|
+
registry_name=args.registry_name,
|
449
|
+
subscription_id=args.subscription,
|
450
|
+
resource_group=args.resource_group,
|
451
|
+
dry_run=args.dry_run,
|
452
|
+
allow_additional_properties=args.allow_additional_properties,
|
453
|
+
override_storage=False)
|
472
454
|
elif args.asset_subcommand == "template":
|
473
455
|
# Create asset template files
|
474
456
|
asset_template(args.folder, args.dry_run)
|
@@ -516,8 +498,7 @@ def main() -> None:
|
|
516
498
|
if not registry_name or not model_name or not version:
|
517
499
|
print("Error: Registry name, model name, and version must be provided", file=sys.stderr)
|
518
500
|
sys.exit(1)
|
519
|
-
|
520
|
-
# Single call to model_get with args values directly
|
501
|
+
# Get model
|
521
502
|
print(model_get(
|
522
503
|
registry_name=registry_name,
|
523
504
|
name=model_name,
|
@@ -553,7 +534,7 @@ def main() -> None:
|
|
553
534
|
print("Error: Registry name and model name must be provided", file=sys.stderr)
|
554
535
|
sys.exit(1)
|
555
536
|
|
556
|
-
#
|
537
|
+
# Delete model
|
557
538
|
model_delete(
|
558
539
|
registry_name=registry_name,
|
559
540
|
name=model_name,
|
@@ -1,3 +1,2 @@
|
|
1
|
-
<!--
|
2
|
-
|
1
|
+
<!-- REMOVE THESE HEADERS AFTER UPDATING -->
|
3
2
|
<!-- `evaluation.md` is highly recommended, but not required. It captures information about the performance of the model. We highly recommend including this section as this information is often used to decide what model to use. -->
|
@@ -432,7 +432,7 @@
|
|
432
432
|
"skuListDefinition": {
|
433
433
|
"type": "string",
|
434
434
|
"description": "A comma-separated list of valid SKUs with no duplicates",
|
435
|
-
"pattern": "^(Standard_(DS3_v2|NC12s_v3|NC16as_T4_v3|NC24ads_A100_v4|NC24rs_v3|NC24s_v3|NC40ads_H100_v5|NC48ads_A100_v4|NC4as_T4_v3|NC64as_T4_v3|NC6s_v3|NC80adis_H100_v5|NC8as_T4_v3|NC96ads_A100_v4|ND40rs_v2|ND96amsr_A100_v4|ND96asr_v4|ND96isr_H100_v5|DS12_v2|DS4_v2|DS5_v2|D16a_v4|D16as_v4|D32a_v4|D32as_v4|D48a_v4|D48as_v4|D64a_v4|D64as_v4|D8a_v4|D8as_v4|D96a_v4|D96as_v4|E16s_v3|E2s_v3|E32s_v3|E48s_v3|E4s_v3|E64s_v3|E8s_v3|F16s_v2|F32s_v2|F48s_v2|F4s_v2|F64s_v2|F72s_v2|F8s_v2|FX12mds|FX24mds|FX36mds|FX48mds|FX4mds|NV12s_v3|NV24s_v3|NV48s_v3))(?:\\s*,\\s*Standard_(DS3_v2|NC12s_v3|NC16as_T4_v3|NC24ads_A100_v4|NC24rs_v3|NC24s_v3|NC40ads_H100_v5|NC48ads_A100_v4|NC4as_T4_v3|NC64as_T4_v3|NC6s_v3|NC80adis_H100_v5|NC8as_T4_v3|NC96ads_A100_v4|ND40rs_v2|ND96amsr_A100_v4|ND96asr_v4|ND96isr_H100_v5|DS12_v2|DS4_v2|DS5_v2|D16a_v4|D16as_v4|D32a_v4|D32as_v4|D48a_v4|D48as_v4|D64a_v4|D64as_v4|D8a_v4|D8as_v4|D96a_v4|D96as_v4|E16s_v3|E2s_v3|E32s_v3|E48s_v3|E4s_v3|E64s_v3|E8s_v3|F16s_v2|F32s_v2|F48s_v2|F4s_v2|F64s_v2|F72s_v2|F8s_v2|FX12mds|FX24mds|FX36mds|FX48mds|FX4mds|NV12s_v3|NV24s_v3|NV48s_v3))*$"
|
435
|
+
"pattern": "^(Standard_(DS3_v2|NC12s_v3|NC16as_T4_v3|NC24ads_A100_v4|NC24rs_v3|NC24s_v3|NC40ads_H100_v5|NC48ads_A100_v4|NC4as_T4_v3|NC64as_T4_v3|NC6s_v3|NC80adis_H100_v5|NC8as_T4_v3|NC96ads_A100_v4|ND40rs_v2|ND96amsr_A100_v4|ND96amsr_v4|ND96asr_v4|ND96isr_H100_v5|DS12_v2|DS4_v2|DS5_v2|D16a_v4|D16as_v4|D32a_v4|D32as_v4|D48a_v4|D48as_v4|D64a_v4|D64as_v4|D8a_v4|D8as_v4|D96a_v4|D96as_v4|E16s_v3|E2s_v3|E32s_v3|E48s_v3|E4s_v3|E64s_v3|E8s_v3|F16s_v2|F32s_v2|F48s_v2|F4s_v2|F64s_v2|F72s_v2|F8s_v2|FX12mds|FX24mds|FX36mds|FX48mds|FX4mds|NV12s_v3|NV24s_v3|NV48s_v3))(?:\\s*,\\s*Standard_(DS3_v2|NC12s_v3|NC16as_T4_v3|NC24ads_A100_v4|NC24rs_v3|NC24s_v3|NC40ads_H100_v5|NC48ads_A100_v4|NC4as_T4_v3|NC64as_T4_v3|NC6s_v3|NC80adis_H100_v5|NC8as_T4_v3|NC96ads_A100_v4|ND40rs_v2|ND96amsr_A100_v4|ND96amsr_v4|ND96asr_v4|ND96isr_H100_v5|DS12_v2|DS4_v2|DS5_v2|D16a_v4|D16as_v4|D32a_v4|D32as_v4|D48a_v4|D48as_v4|D64a_v4|D64as_v4|D8a_v4|D8as_v4|D96a_v4|D96as_v4|E16s_v3|E2s_v3|E32s_v3|E48s_v3|E4s_v3|E64s_v3|E8s_v3|F16s_v2|F32s_v2|F48s_v2|F4s_v2|F64s_v2|F72s_v2|F8s_v2|FX12mds|FX24mds|FX36mds|FX48mds|FX4mds|NV12s_v3|NV24s_v3|NV48s_v3))*$"
|
436
436
|
},
|
437
437
|
"skuEnum": {
|
438
438
|
"enum": [
|
@@ -452,6 +452,7 @@
|
|
452
452
|
"Standard_NC96ads_A100_v4",
|
453
453
|
"Standard_ND40rs_v2",
|
454
454
|
"Standard_ND96amsr_A100_v4",
|
455
|
+
"Standard_ND96amsr_v4",
|
455
456
|
"Standard_ND96asr_v4",
|
456
457
|
"Standard_ND96isr_H100_v5",
|
457
458
|
"Standard_DS12_v2",
|
@@ -1,3 +1,2 @@
|
|
1
|
-
<!--
|
2
|
-
|
3
|
-
<!-- `notes.md` is highly recommended, but not required. It captures information about how your model is created. We highly recommend including this section to provide transparency for the customers. -->
|
1
|
+
<!-- REMOVE THESE HEADERS AFTER UPDATING -->
|
2
|
+
<!-- `notes.md` is highly recommended, but not required. It captures information about how your model is created. We highly recommend including this section to provide transparency for the customers. -->
|
@@ -53,7 +53,8 @@ def load_schema(schema_file: Path, allow_additional_properties: bool = False) ->
|
|
53
53
|
def validate_model_schema(input_dirs: List[Path],
|
54
54
|
schema_file: Path,
|
55
55
|
asset_config_filename: str,
|
56
|
-
allow_additional_properties: bool = False
|
56
|
+
allow_additional_properties: bool = False,
|
57
|
+
changed_files: List[Path] = None) -> bool:
|
57
58
|
"""Validate model variant schema.
|
58
59
|
|
59
60
|
Args:
|
@@ -61,6 +62,7 @@ def validate_model_schema(input_dirs: List[Path],
|
|
61
62
|
schema_file (Path): File containing model variant schema.
|
62
63
|
asset_config_filename (str): Asset config filename to search for.
|
63
64
|
allow_additional_properties (bool): Whether to allow additional properties not defined in schema.
|
65
|
+
changed_files (List[Path], optional): List of changed files, used to filter assets. Defaults to None.
|
64
66
|
|
65
67
|
Returns:
|
66
68
|
bool: True on success.
|
@@ -71,63 +73,82 @@ def validate_model_schema(input_dirs: List[Path],
|
|
71
73
|
# Create validator instance for collecting all errors
|
72
74
|
validator = jsonschema.Draft7Validator(loaded_schema)
|
73
75
|
|
76
|
+
# Gather list of just changed assets, for later filtering
|
77
|
+
changed_assets = util.find_asset_config_files(input_dirs, asset_config_filename, changed_files) if changed_files else None # noqa: E501
|
78
|
+
|
74
79
|
asset_count = 0
|
75
80
|
model_count = 0
|
81
|
+
changed_model_count = 0
|
76
82
|
error_count = 0
|
77
83
|
for input_dir in input_dirs:
|
78
84
|
# Recursively find all files with the name matching asset_config_filename
|
79
|
-
for
|
85
|
+
for asset_config_path in util.find_asset_config_files(input_dir, asset_config_filename):
|
80
86
|
asset_count += 1
|
87
|
+
|
88
|
+
validate_this = changed_assets is None or asset_config_path in changed_assets
|
89
|
+
|
90
|
+
try:
|
91
|
+
asset_config = assets.AssetConfig(asset_config_path)
|
92
|
+
except Exception as e:
|
93
|
+
raise Exception(f"Error loading asset config from {asset_config_path}: {e}")
|
94
|
+
|
81
95
|
file_path = asset_config.spec_with_path
|
96
|
+
|
82
97
|
if asset_config.type == assets.AssetType.MODEL:
|
83
98
|
model_count += 1
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
99
|
+
|
100
|
+
if validate_this:
|
101
|
+
changed_model_count += 1
|
102
|
+
# Validate the file against the schema
|
103
|
+
try:
|
104
|
+
with open(file_path, "r") as f:
|
105
|
+
spec_config = yaml.safe_load(f)
|
106
|
+
|
107
|
+
# Collect all validation errors
|
108
|
+
errors = list(validator.iter_errors(spec_config))
|
109
|
+
|
110
|
+
if not errors:
|
111
|
+
logger.print(f"{file_path} is valid.")
|
112
|
+
else:
|
113
|
+
logger.log_error(f"\n‼️{file_path} has {len(errors)} validation error(s):")
|
114
|
+
|
115
|
+
for e in errors:
|
116
|
+
# Get detailed error information for each error
|
117
|
+
error_path = '.'.join(str(p) for p in e.path) if e.path else "root"
|
118
|
+
line_info = ""
|
119
|
+
|
120
|
+
# Get line number from jsonschema error if available
|
121
|
+
if hasattr(e, 'lineno') and e.lineno is not None:
|
122
|
+
line_info = f" at line {e.lineno}"
|
123
|
+
else:
|
124
|
+
# Try to find line number by looking at the path and instance
|
125
|
+
try:
|
126
|
+
with open(file_path, "r") as f:
|
127
|
+
yaml_content = f.readlines()
|
128
|
+
yaml_lines = []
|
129
|
+
for idx, line in enumerate(yaml_content):
|
130
|
+
if error_path in line:
|
131
|
+
yaml_lines.append(f"line {idx+1}: {line.strip()}")
|
132
|
+
if yaml_lines:
|
133
|
+
line_info = "\nPossible location(s):\n " + "\n ".join(yaml_lines)
|
134
|
+
except Exception:
|
135
|
+
pass
|
136
|
+
|
137
|
+
schema_path = '.'.join(str(p) for p in e.schema_path)
|
138
|
+
logger.print(f"⚠️ {file_path} is invalid at path '{error_path}'{line_info}:")
|
139
|
+
logger.print(f" Error: {e.message}")
|
140
|
+
logger.print(f" Instance: {e.instance}")
|
141
|
+
logger.print(f" Schema path: {schema_path}")
|
142
|
+
error_count += 1
|
143
|
+
except Exception as e:
|
144
|
+
logger.log_error(f"Error processing {file_path}: {str(e)}")
|
124
145
|
error_count += 1
|
125
|
-
except Exception as e:
|
126
|
-
logger.log_error(f"Error processing {file_path}: {str(e)}")
|
127
|
-
error_count += 1
|
128
146
|
|
129
147
|
logger.print(f"Found {asset_count} total asset(s).")
|
130
|
-
|
148
|
+
if changed_assets is not None:
|
149
|
+
logger.print(f"Found {error_count} model(s) with error(s) out of {changed_model_count} total changed model(s)")
|
150
|
+
else:
|
151
|
+
logger.print(f"Found {error_count} model(s) with error(s) out of {model_count} total model(s)")
|
131
152
|
return error_count == 0
|
132
153
|
|
133
154
|
|
@@ -142,16 +163,20 @@ if __name__ == "__main__":
|
|
142
163
|
help="Asset config file name to search for")
|
143
164
|
parser.add_argument("--allow-additional-properties", action="store_true",
|
144
165
|
help="Allow additional properties not defined in the schema")
|
166
|
+
parser.add_argument("-c", "--changed-files",
|
167
|
+
help="Comma-separated list of changed files, used to filter assets")
|
145
168
|
args = parser.parse_args()
|
146
169
|
|
147
170
|
# Convert comma-separated values to lists
|
148
171
|
input_dirs = [Path(d) for d in args.input_dirs.split(",")]
|
172
|
+
changed_files = [Path(f) for f in args.changed_files.split(",")] if args.changed_files else []
|
149
173
|
|
150
174
|
# Validate against model schema
|
151
175
|
success = validate_model_schema(input_dirs=input_dirs,
|
152
176
|
schema_file=args.schema_file,
|
153
177
|
asset_config_filename=args.asset_config_filename,
|
154
|
-
allow_additional_properties=args.allow_additional_properties
|
178
|
+
allow_additional_properties=args.allow_additional_properties,
|
179
|
+
changed_files=changed_files)
|
155
180
|
|
156
181
|
if not success:
|
157
182
|
sys.exit(1)
|
@@ -7,7 +7,7 @@ import sys
|
|
7
7
|
import shutil
|
8
8
|
import tempfile
|
9
9
|
import yaml
|
10
|
-
from datetime import datetime
|
10
|
+
from datetime import datetime
|
11
11
|
from pathlib import Path
|
12
12
|
from typing import List
|
13
13
|
|
@@ -16,7 +16,6 @@ from azure.identity import DefaultAzureCredential
|
|
16
16
|
|
17
17
|
from azureml.registry.data.validate_model_schema import validate_model_schema
|
18
18
|
from azureml.registry.data.validate_model_variant_schema import validate_model_variant_schema
|
19
|
-
from azureml.registry.mgmt.registry_config import RegistryConfig
|
20
19
|
|
21
20
|
# Windows compatibility patch - must be applied before importing azureml.assets
|
22
21
|
from subprocess import run
|
@@ -34,7 +33,7 @@ publish_utils.run_command = patched_run_command
|
|
34
33
|
|
35
34
|
import azureml.assets as assets # noqa: E402
|
36
35
|
import azureml.assets.util as util # noqa: E402
|
37
|
-
from azureml.assets.config import AssetConfig, AssetType
|
36
|
+
from azureml.assets.config import AssetConfig, AssetType # noqa: E402
|
38
37
|
from azureml.assets.publish_utils import create_asset # noqa: E402
|
39
38
|
from azureml.assets.validate_assets import validate_assets # noqa: E402
|
40
39
|
|
@@ -88,34 +87,13 @@ def validate_model(asset_path: Path, allow_additional_properties: bool = False)
|
|
88
87
|
return True
|
89
88
|
|
90
89
|
|
91
|
-
def
|
92
|
-
"""Use storage configuration and generate/set SAS token.
|
93
|
-
|
94
|
-
Args:
|
95
|
-
asset (AssetConfig): Asset configuration object to modify
|
96
|
-
storage_config (dict): Storage configuration dictionary
|
97
|
-
"""
|
98
|
-
if not storage_config:
|
99
|
-
# No storage overrides provided, skip storage configuration
|
100
|
-
return
|
101
|
-
|
102
|
-
print("Overriding storage configuration with provided values...")
|
103
|
-
extra_config = asset.extra_config_as_object()
|
104
|
-
extra_config._path = AzureBlobstoreAssetPath(
|
105
|
-
storage_name=storage_config["storage_name"],
|
106
|
-
container_name=storage_config["container_name"],
|
107
|
-
container_path=storage_config["container_path"]
|
108
|
-
)
|
109
|
-
_ = extra_config.path.get_uri(token_expiration=timedelta(hours=1))
|
110
|
-
|
111
|
-
|
112
|
-
def build_mutable_asset(base_asset: AssetConfig, mutable_asset_dir: str, storage_overrides_exist: bool = False) -> AssetConfig:
|
90
|
+
def build_mutable_asset(base_asset: AssetConfig, mutable_asset_dir: str, override_storage: bool = False) -> AssetConfig:
|
113
91
|
"""Build a mutable copy of the asset in a temporary directory.
|
114
92
|
|
115
93
|
Args:
|
116
94
|
base_asset (AssetConfig): Base asset configuration to copy
|
117
95
|
mutable_asset_dir (str): Directory path for the mutable asset copy
|
118
|
-
|
96
|
+
override_storage (bool, optional): If True, model config will be modified to reference a local temp file.
|
119
97
|
|
120
98
|
Returns:
|
121
99
|
AssetConfig: Mutable asset configuration object
|
@@ -136,63 +114,75 @@ def build_mutable_asset(base_asset: AssetConfig, mutable_asset_dir: str, storage
|
|
136
114
|
spec_config_file = mutable_asset_dir / base_spec_file.relative_to(common_dir)
|
137
115
|
model_config_file = mutable_asset_dir / base_model_file.relative_to(common_dir)
|
138
116
|
|
139
|
-
#
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
117
|
+
# Override storage info for model card preview
|
118
|
+
if override_storage:
|
119
|
+
print("Model card preview - Default setting version and storage info")
|
120
|
+
|
121
|
+
# Autoincrement version for mutable asset
|
122
|
+
with open(spec_config_file, "r") as f:
|
123
|
+
spec_config = yaml.safe_load(f)
|
124
|
+
spec_config["version"] = datetime.now().strftime("%Y%m%d%H%M%S")
|
125
|
+
|
126
|
+
with open(spec_config_file, "w") as f:
|
127
|
+
yaml.dump(spec_config, f)
|
128
|
+
|
129
|
+
# Create dummy file to upload to storage
|
130
|
+
with open(mutable_asset_dir / "dummy.txt", "w") as f:
|
131
|
+
f.write("This is a dummy file used in the artifact for model card preview.")
|
132
|
+
|
133
|
+
yaml_content = """
|
134
|
+
path:
|
135
|
+
uri: ./dummy.txt
|
136
|
+
type: local
|
137
|
+
publish:
|
138
|
+
description: description.md
|
139
|
+
type: custom_model
|
140
|
+
"""
|
141
|
+
new_model_config = yaml.safe_load(yaml_content)
|
142
|
+
|
143
|
+
# Overwrite model config
|
154
144
|
with open(model_config_file, "w") as f:
|
155
|
-
yaml.dump(
|
145
|
+
yaml.dump(new_model_config, f)
|
156
146
|
|
157
147
|
mutable_asset = AssetConfig(asset_config_file)
|
158
148
|
|
159
149
|
return mutable_asset
|
160
150
|
|
161
151
|
|
162
|
-
def create_or_update_asset(readonly_asset: AssetConfig,
|
152
|
+
def create_or_update_asset(readonly_asset: AssetConfig, registry_name: str, subscription_id: str, resource_group: str, override_storage: bool = False):
|
163
153
|
"""Create or update an asset in the AzureML registry.
|
164
154
|
|
165
155
|
Args:
|
166
156
|
readonly_asset (AssetConfig): Asset configuration to create or update
|
167
|
-
|
157
|
+
registry_name (str): Name of AzureML registry to deploy to
|
158
|
+
subscription_id (str): Subscription ID of AzureML registry to deploy to
|
159
|
+
resource_group (str): Resource group of AzureML registry to deploy to
|
160
|
+
override_storage (bool): Whether to override storage settings
|
168
161
|
"""
|
169
162
|
print("[CREATING/UPDATING ASSET]")
|
170
|
-
print(f"
|
163
|
+
print(f"Registry name: {registry_name}, Subscription ID: {subscription_id}, Resource group: {resource_group}")
|
164
|
+
|
171
165
|
# Create ML client
|
172
166
|
ml_client = MLClient(
|
173
|
-
subscription_id=
|
174
|
-
resource_group_name=
|
175
|
-
registry_name=
|
167
|
+
subscription_id=subscription_id,
|
168
|
+
resource_group_name=resource_group,
|
169
|
+
registry_name=registry_name,
|
176
170
|
credential=DefaultAzureCredential(),
|
177
171
|
)
|
178
172
|
|
179
173
|
with tempfile.TemporaryDirectory() as mutable_asset_dir:
|
180
|
-
mutable_asset = build_mutable_asset(base_asset=readonly_asset, mutable_asset_dir=mutable_asset_dir,
|
181
|
-
# autoincrement version
|
174
|
+
mutable_asset = build_mutable_asset(base_asset=readonly_asset, mutable_asset_dir=mutable_asset_dir, override_storage=override_storage)
|
182
175
|
try:
|
183
|
-
|
184
|
-
|
176
|
+
success = create_asset(mutable_asset, registry_name, ml_client)
|
177
|
+
if not success:
|
178
|
+
raise RuntimeError(f"Failed to create/update asset: create_asset 'success' returned {success}")
|
185
179
|
except Exception as e:
|
186
180
|
print(f"Failed to create/update asset: {e}")
|
187
181
|
raise
|
188
182
|
|
189
|
-
if not success:
|
190
|
-
print(f"Failed to create/update asset: create_asset 'success' returned {success}")
|
191
|
-
raise
|
192
|
-
|
193
183
|
print("\n[VALIDATE YOUR ASSET IN THE UI HERE]")
|
194
|
-
print(f" - Model Catalog link: https://ai.azure.com/explore/models/{mutable_asset.name}/version/{mutable_asset.version}/registry/{
|
195
|
-
print(f" - Azure Portal link: https://ml.azure.com/registries/{
|
184
|
+
print(f" - Model Catalog link: https://ai.azure.com/explore/models/{mutable_asset.name}/version/{mutable_asset.version}/registry/{registry_name}")
|
185
|
+
print(f" - Azure Portal link: https://ml.azure.com/registries/{registry_name}/models/{mutable_asset.name}/version/{mutable_asset.version}")
|
196
186
|
|
197
187
|
|
198
188
|
def asset_validate(asset_path: Path, dry_run: bool = False, allow_additional_properties: bool = False) -> bool:
|
@@ -237,31 +227,29 @@ def asset_validate(asset_path: Path, dry_run: bool = False, allow_additional_pro
|
|
237
227
|
return validate_model(readonly_asset.file_path, allow_additional_properties)
|
238
228
|
|
239
229
|
|
240
|
-
def asset_deploy(asset_path: Path,
|
241
|
-
"""Deploy an asset
|
230
|
+
def asset_deploy(asset_path: Path, registry_name: str, subscription_id: str, resource_group: str, dry_run: bool = False, allow_additional_properties: bool = False, override_storage: bool = False) -> bool:
|
231
|
+
"""Deploy an asset to a registry.
|
242
232
|
|
243
233
|
Args:
|
244
234
|
asset_path (Path): Path to the asset folder to deploy
|
245
|
-
config_path (Path): Path to configuration file
|
246
235
|
dry_run (bool): If True, perform a dry run without deploying
|
236
|
+
allow_additional_properties (bool): Whether to allow additional properties not defined in schema
|
237
|
+
override_storage (bool): Whether to override storage settings
|
247
238
|
|
248
239
|
Returns:
|
249
240
|
bool: True if deployment succeeds, False otherwise
|
250
241
|
"""
|
251
|
-
try:
|
252
|
-
config = RegistryConfig(config_path)
|
253
|
-
except Exception as e:
|
254
|
-
print(f"❌ [ERROR]: Configuration validation failed: {e}")
|
255
|
-
return False
|
256
|
-
|
257
242
|
if dry_run:
|
258
|
-
|
243
|
+
if override_storage:
|
244
|
+
print(f"[DRY RUN] Would preview asset at {asset_path} to registry {registry_name}")
|
245
|
+
else:
|
246
|
+
print(f"[DRY RUN] Would deploy asset at {asset_path} to registry {registry_name}")
|
259
247
|
return True
|
260
248
|
|
261
249
|
asset_path = asset_path.resolve()
|
262
250
|
|
263
251
|
# Validate asset before deployment
|
264
|
-
if not asset_validate(asset_path, dry_run=False):
|
252
|
+
if not asset_validate(asset_path, dry_run=False, allow_additional_properties=allow_additional_properties):
|
265
253
|
print("❌ [ERROR]: Asset validation failed. Asset deployment aborted.")
|
266
254
|
return False
|
267
255
|
|
@@ -269,7 +257,7 @@ def asset_deploy(asset_path: Path, config_path: Path, dry_run: bool = False) ->
|
|
269
257
|
readonly_asset = assets.AssetConfig(asset_path / assets.DEFAULT_ASSET_FILENAME)
|
270
258
|
|
271
259
|
try:
|
272
|
-
create_or_update_asset(readonly_asset,
|
260
|
+
create_or_update_asset(readonly_asset, registry_name, subscription_id, resource_group, override_storage)
|
273
261
|
return True
|
274
262
|
except Exception as e:
|
275
263
|
print(f"❌ [ERROR]: Failed to deploy asset: {e}")
|
{azureml_registry_tools-0.1.0a14.dist-info → azureml_registry_tools-0.1.0a16.dist-info}/RECORD
RENAMED
@@ -1,7 +1,7 @@
|
|
1
1
|
azureml/__init__.py,sha256=_gYz_vABVrp9EyOZEYn4Ya8XotJC2rZn-b9kFTEj1Dk,266
|
2
2
|
azureml/registry/__init__.py,sha256=qjP86n1Yz6hdZb3az-wjfi7LNndsFjMQI6lXmKfXapM,266
|
3
3
|
azureml/registry/_cli/__init__.py,sha256=dJ020ynrregpUaNGu8xVLLmX3cC9DAjaBMP1qnljLEE,208
|
4
|
-
azureml/registry/_cli/registry_syndication_cli.py,sha256=
|
4
|
+
azureml/registry/_cli/registry_syndication_cli.py,sha256=7LyyBDC5OnJu9OMBAl_L_SWs9jB0hjRdhdeLqTFXFfg,28166
|
5
5
|
azureml/registry/_cli/repo2registry_cli.py,sha256=4CDv4tYWLTjVgdXIcoKA9iu_gOv_Z_xn05wSANkdmdg,5378
|
6
6
|
azureml/registry/_rest_client/__init__.py,sha256=Eh0vB8AVlwkZlHLO4DCGHyyfRYYgeTeVjiUAX_WujG0,219
|
7
7
|
azureml/registry/_rest_client/arm_client.py,sha256=KVSj0V1bN-vCUV3fBbIdZDpWTLKYT6qdWIZtDjx2la4,4516
|
@@ -10,30 +10,29 @@ azureml/registry/_rest_client/registry_management_client.py,sha256=3-PBwj91lkG1y
|
|
10
10
|
azureml/registry/_rest_client/registry_model_client.py,sha256=LqJGTuYQtBnHSeSbOl5KVbiO6vGBkKQ7HD5jc4fvV3k,14466
|
11
11
|
azureml/registry/data/__init__.py,sha256=cW3X6HATz6XF-K_7uKdybTbJb9EZSecBN4J27NGdZmU,231
|
12
12
|
azureml/registry/data/asset.yaml.template,sha256=WTgfuvKEBp-EVFSQ0JpU0h4z_ULJdULO9kHmB_9Fr1o,96
|
13
|
-
azureml/registry/data/description.md.template,sha256=
|
14
|
-
azureml/registry/data/evaluation.md.template,sha256=
|
13
|
+
azureml/registry/data/description.md.template,sha256=wQLk54U8hoXU1y9235R4irc6FGYPXGO-x9EHUorP15Q,84
|
14
|
+
azureml/registry/data/evaluation.md.template,sha256=JaDecIfLV9vZDUrZzVRPzVHHnKD-BQGBgQ-cw1dHavU,277
|
15
15
|
azureml/registry/data/model-variant.schema.json,sha256=AT4Dy6cCtp_SFUfSqYIqcER8AldpYm0QIEy1abY3QWE,1699
|
16
|
-
azureml/registry/data/model.schema.json,sha256=
|
16
|
+
azureml/registry/data/model.schema.json,sha256=TORbhePqEYovjg2Cem-JGJL7Tm-EbA00WvYeybMuWO4,26118
|
17
17
|
azureml/registry/data/model.yaml.template,sha256=h5uqAN22FLaWrbPxIb8yVKH9cGDBrIwooXYYfsKhxDw,245
|
18
|
-
azureml/registry/data/notes.md.template,sha256=
|
19
|
-
azureml/registry/data/validate_model_schema.py,sha256=
|
18
|
+
azureml/registry/data/notes.md.template,sha256=zSRyOR__9NGL2j0tugY7HgFkwkAdcE2pJyyyGsz1SAk,248
|
19
|
+
azureml/registry/data/validate_model_schema.py,sha256=OQp2E01kdxSphvUQYQvelSiD24-qUG6nTFuzW60wX2c,8322
|
20
20
|
azureml/registry/data/validate_model_variant_schema.py,sha256=JPVNtRBn6qciMu4PaRXOvS86OGGW0cocL2Rri4xYKo8,3629
|
21
21
|
azureml/registry/mgmt/__init__.py,sha256=LMhqcEC8ItmmpKZljElGXH-6olHlT3SLl0dJU01OvuM,226
|
22
|
-
azureml/registry/mgmt/asset_management.py,sha256=
|
22
|
+
azureml/registry/mgmt/asset_management.py,sha256=bipZR_yLMEka0PU-vaPDhBsc9D5veTacrHYwaIT5Dpw,10977
|
23
23
|
azureml/registry/mgmt/create_asset_template.py,sha256=ejwLuIsmzJOoUePoxbM-eGMg2E3QHfdX-nPMBzYUVMQ,3525
|
24
24
|
azureml/registry/mgmt/create_manifest.py,sha256=N9wRmjAKO09A3utN_lCUsM_Ufpj7PL0SJz-XHPHWuyM,9528
|
25
25
|
azureml/registry/mgmt/create_model_spec.py,sha256=1PdAcUf-LomvljoT8wKQihXMTLd7DoTgN0qDX4Lol1A,10473
|
26
26
|
azureml/registry/mgmt/model_management.py,sha256=STTr_uvdPKV2NaJ5UvS5aMi3yejVF6Hkj9DjofJLQik,7453
|
27
|
-
azureml/registry/mgmt/registry_config.py,sha256=NhIkTCNlfbfJrVGw61AmBAIZQ5HU2cb4kXAI9j3Wwy4,7181
|
28
27
|
azureml/registry/mgmt/syndication_manifest.py,sha256=8Sfd49QuCA5en5_mIOLE21kZVpnReUXowx_g0TVRgWg,9025
|
29
28
|
azureml/registry/tools/__init__.py,sha256=IAuWWpGfZm__pAkBIxmpJz84QskpkxBr0yDk1TUSnkE,223
|
30
29
|
azureml/registry/tools/config.py,sha256=tjPaoBsWtPXBL8Ww1hcJtsr2SuIjPKt79dR8iovcebg,3639
|
31
30
|
azureml/registry/tools/create_or_update_assets.py,sha256=Q-_BV7KWn1huQn5JriKT_8xJNoQQ_HK5wCftrq9DepA,15988
|
32
31
|
azureml/registry/tools/registry_utils.py,sha256=zgYlCiOONtQJ4yZ9wg8tKVoE8dh6rrjB8hYBGhpV9-0,1403
|
33
32
|
azureml/registry/tools/repo2registry_config.py,sha256=eXp_tU8Jyi30g8xGf7wbpLgKEPpieohBANKxMSLzq7s,4873
|
34
|
-
azureml_registry_tools-0.1.
|
35
|
-
azureml_registry_tools-0.1.
|
36
|
-
azureml_registry_tools-0.1.
|
37
|
-
azureml_registry_tools-0.1.
|
38
|
-
azureml_registry_tools-0.1.
|
39
|
-
azureml_registry_tools-0.1.
|
33
|
+
azureml_registry_tools-0.1.0a16.dist-info/licenses/LICENSE.txt,sha256=n20rxwp7_NGrrShv9Qvcs90sjI1l3Pkt3m-5OPCWzgs,845
|
34
|
+
azureml_registry_tools-0.1.0a16.dist-info/METADATA,sha256=tQuJc5f47M5C2roGH_tm4D9elTB_DmW9G_1YNaLrnHw,522
|
35
|
+
azureml_registry_tools-0.1.0a16.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
36
|
+
azureml_registry_tools-0.1.0a16.dist-info/entry_points.txt,sha256=iRUkAeQidMnO6RQzpLqMUBTcyYtNzAfSin9WnSdVGLw,147
|
37
|
+
azureml_registry_tools-0.1.0a16.dist-info/top_level.txt,sha256=ZOeEa0TAXo6i5wOjwBoqfIGEuxOcKuscGgNSpizqREY,8
|
38
|
+
azureml_registry_tools-0.1.0a16.dist-info/RECORD,,
|
@@ -1,147 +0,0 @@
|
|
1
|
-
# ---------------------------------------------------------
|
2
|
-
# Copyright (c) Microsoft Corporation. All rights reserved.
|
3
|
-
# ---------------------------------------------------------
|
4
|
-
|
5
|
-
"""RegistryConfig class."""
|
6
|
-
|
7
|
-
import configparser
|
8
|
-
from pathlib import Path
|
9
|
-
from typing import Dict
|
10
|
-
|
11
|
-
|
12
|
-
class RegistryConfig:
|
13
|
-
"""RegistryConfig class."""
|
14
|
-
|
15
|
-
def __init__(self, config_path: Path = None):
|
16
|
-
"""Registry config init.
|
17
|
-
|
18
|
-
Args:
|
19
|
-
config_path (Path, optional): Path to configuration file. Defaults to "registry-mgmt.cfg".
|
20
|
-
"""
|
21
|
-
if config_path is None:
|
22
|
-
print("No config path provided, using default 'registry-mgmt.cfg'.")
|
23
|
-
config_path = Path("registry-mgmt.cfg")
|
24
|
-
self.config_path = config_path
|
25
|
-
if not self.config_path.is_file():
|
26
|
-
raise FileNotFoundError(f"File '{self.config_path.resolve().as_posix()}' does not exist.")
|
27
|
-
|
28
|
-
self.config = configparser.ConfigParser()
|
29
|
-
self.config.read(self.config_path)
|
30
|
-
self._validate_schema()
|
31
|
-
|
32
|
-
def _validate_schema(self) -> None:
|
33
|
-
"""Validate registry config schema."""
|
34
|
-
config_file_name = str(self.config_path)
|
35
|
-
|
36
|
-
if not self.config.has_section("registry"):
|
37
|
-
raise Exception(f'"registry" section not found in config file {config_file_name}')
|
38
|
-
|
39
|
-
# Validate registry section
|
40
|
-
if not self.config.has_option("registry", "registry_name"):
|
41
|
-
raise Exception(f'Key "registry_name" not found under "registry" section in config file {config_file_name}')
|
42
|
-
if not self.config.has_option("registry", "tenant_id"):
|
43
|
-
raise Exception(f'Key "tenant_id" not found under "registry" section in config file {config_file_name}')
|
44
|
-
if not self.config.has_option("registry", "subscription_id"):
|
45
|
-
raise Exception(f'Key "subscription_id" not found under "registry" section in config file {config_file_name}')
|
46
|
-
if not self.config.has_option("registry", "resource_group"):
|
47
|
-
raise Exception(f'Key "resource_group" not found under "registry" section in config file {config_file_name}')
|
48
|
-
|
49
|
-
# Validate that values are not empty
|
50
|
-
required_settings = ["registry_name", "tenant_id", "subscription_id", "resource_group"]
|
51
|
-
for setting in required_settings:
|
52
|
-
if not self.config.get("registry", setting).strip():
|
53
|
-
raise Exception(f'Value for "{setting}" is empty in "registry" section in config file {config_file_name}')
|
54
|
-
|
55
|
-
# Validate storage_overrides section (optional, but if present, validate its contents)
|
56
|
-
if self.config.has_section("storage_overrides"):
|
57
|
-
allowed_storage_keys = {"storage_name", "container_name", "container_path"}
|
58
|
-
actual_storage_keys = set(self.config.options("storage_overrides"))
|
59
|
-
|
60
|
-
# Check for unexpected keys
|
61
|
-
unexpected_keys = actual_storage_keys - allowed_storage_keys
|
62
|
-
if unexpected_keys:
|
63
|
-
raise Exception(f'Unexpected keys {sorted(unexpected_keys)} found in "storage_overrides" section in config file {config_file_name}. Only {sorted(allowed_storage_keys)} are allowed.')
|
64
|
-
|
65
|
-
# Check for required keys
|
66
|
-
if not self.config.has_option("storage_overrides", "storage_name"):
|
67
|
-
raise Exception(f'Key "storage_name" not found under "storage_overrides" section in config file {config_file_name}')
|
68
|
-
if not self.config.has_option("storage_overrides", "container_name"):
|
69
|
-
raise Exception(f'Key "container_name" not found under "storage_overrides" section in config file {config_file_name}')
|
70
|
-
if not self.config.has_option("storage_overrides", "container_path"):
|
71
|
-
raise Exception(f'Key "container_path" not found under "storage_overrides" section in config file {config_file_name}')
|
72
|
-
|
73
|
-
# Validate that storage values are not empty
|
74
|
-
required_storage_settings = ["storage_name", "container_name", "container_path"]
|
75
|
-
for setting in required_storage_settings:
|
76
|
-
if not self.config.get("storage_overrides", setting).strip():
|
77
|
-
raise Exception(f'Value for "{setting}" is empty in "storage_overrides" section in config file {config_file_name}')
|
78
|
-
|
79
|
-
@property
|
80
|
-
def registry_name(self) -> str:
|
81
|
-
"""Get registry name from config."""
|
82
|
-
return self.config.get("registry", "registry_name")
|
83
|
-
|
84
|
-
@property
|
85
|
-
def tenant_id(self) -> str:
|
86
|
-
"""Get tenant ID from config."""
|
87
|
-
return self.config.get("registry", "tenant_id")
|
88
|
-
|
89
|
-
@property
|
90
|
-
def subscription_id(self) -> str:
|
91
|
-
"""Get subscription ID from config."""
|
92
|
-
return self.config.get("registry", "subscription_id")
|
93
|
-
|
94
|
-
@property
|
95
|
-
def resource_group(self) -> str:
|
96
|
-
"""Get resource group from config."""
|
97
|
-
return self.config.get("registry", "resource_group")
|
98
|
-
|
99
|
-
@property
|
100
|
-
def storage_config(self) -> Dict[str, str]:
|
101
|
-
"""Get storage configuration."""
|
102
|
-
if self.config.has_section("storage_overrides"):
|
103
|
-
return dict(self.config["storage_overrides"])
|
104
|
-
return {}
|
105
|
-
|
106
|
-
|
107
|
-
def create_registry_config(registry_name: str, subscription_id: str, resource_group: str, tenant_id: str,
|
108
|
-
config_file_path: Path, storage_name: str = None, container_name: str = None,
|
109
|
-
container_path: str = None):
|
110
|
-
"""Create registry config.
|
111
|
-
|
112
|
-
Args:
|
113
|
-
registry_name (str): Registry name.
|
114
|
-
subscription_id (str): Registry subscription id.
|
115
|
-
resource_group (str): Registry resource group.
|
116
|
-
tenant_id (str): Tenant ID.
|
117
|
-
config_file_path (Path): Path to config file.
|
118
|
-
storage_name (str, optional): Storage account name for storage overrides. Defaults to None.
|
119
|
-
container_name (str, optional): Container name for storage overrides. Defaults to None.
|
120
|
-
container_path (str, optional): Container path for storage overrides. Defaults to None.
|
121
|
-
"""
|
122
|
-
print("Creating registry config...")
|
123
|
-
|
124
|
-
registry_config = configparser.ConfigParser()
|
125
|
-
registry_config.add_section("registry")
|
126
|
-
registry_config.set("registry", "registry_name", registry_name)
|
127
|
-
registry_config.set("registry", "subscription_id", subscription_id)
|
128
|
-
registry_config.set("registry", "resource_group", resource_group)
|
129
|
-
registry_config.set("registry", "tenant_id", tenant_id)
|
130
|
-
|
131
|
-
# Add storage overrides if provided
|
132
|
-
if storage_name and container_name and container_path:
|
133
|
-
registry_config.add_section("storage_overrides")
|
134
|
-
registry_config.set("storage_overrides", "storage_name", storage_name)
|
135
|
-
registry_config.set("storage_overrides", "container_name", container_name)
|
136
|
-
registry_config.set("storage_overrides", "container_path", container_path)
|
137
|
-
|
138
|
-
# Write to path
|
139
|
-
if config_file_path is None:
|
140
|
-
print('No config file path provided, using default "registry-mgmt.cfg"')
|
141
|
-
config_file_path = Path("registry-mgmt.cfg")
|
142
|
-
with open(config_file_path, "w") as config_file:
|
143
|
-
registry_config.write(config_file)
|
144
|
-
|
145
|
-
config_abs_path = Path(config_file_path).resolve().as_posix()
|
146
|
-
|
147
|
-
print(f"Wrote registry config file to {config_abs_path}")
|
{azureml_registry_tools-0.1.0a14.dist-info → azureml_registry_tools-0.1.0a16.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|