Skip to content

Commit 0f86392

Browse files
authored
Sundry fixes for CNF quickstart (Azure#38)
* Sundry fixes for CNF quickstart * merge add-aosm-ext in (Azure#37) * markups
1 parent f06efc3 commit 0f86392

File tree

13 files changed

+408
-242
lines changed

13 files changed

+408
-242
lines changed

src/aosm/HISTORY.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ unreleased
99
* NFDV version exposed as a CGV on an SNS.
1010
* `az aosm nfd publish` option added for `--definition-type cnf` to publish the CNF bicep templates, upload helm charts from disk to the ACR and copy the images from a source ACR to the target ACR.
1111
* Managed Identity added to VNF NF templates - requires subscription to be registered for the feature flag.
12+
* Various fixes to NFD build of deployParameters schema and interactive mode create of deployParameters mappings file.
13+
* Fix CNF NFD publish so that it doesn't render the ACR unuseable for future Artifact publishing.
14+
* Allow CNF NFD image copy from a source ACR using a namespace.
15+
* Fix - Add new CGSchema parameters not from the NFD to the `required` section of the schema.
16+
* Add the ability to skip bicep publish or artifact upload during publish commands.
17+
* Fix Manifest name for NSDs so it isn't the same as that for NFDs
18+
* Add validation of source_registry_id format for CNF configuration
1219

1320
0.2.0
1421
++++++

src/aosm/azext_aosm/_configuration.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
import re
23
from dataclasses import dataclass, field
34
from pathlib import Path
45
from typing import Any, Dict, List, Optional
@@ -12,6 +13,7 @@
1213
NSD,
1314
NSD_OUTPUT_BICEP_PREFIX,
1415
VNF,
16+
SOURCE_ACR_REGEX
1517
)
1618

1719
DESCRIPTION_MAP: Dict[str, str] = {
@@ -95,6 +97,13 @@
9597
"source_registry_id": (
9698
"Resource ID of the source acr registry from which to pull the image"
9799
),
100+
"source_registry_namespace": (
101+
"Optional. Namespace of the repository of the source acr registry from which "
102+
"to pull. For example if your repository is samples/prod/nginx then set this to"
103+
" samples/prod . Leave blank if the image is in the root namespace."
104+
"See https://learn.microsoft.com/en-us/azure/container-registry/"
105+
"container-registry-best-practices#repository-namespaces for further details."
106+
),
98107
}
99108

100109

@@ -220,8 +229,10 @@ def network_function_name(self) -> str:
220229
@property
221230
def acr_manifest_name(self) -> str:
222231
"""Return the ACR manifest name from the NFD name."""
223-
sanitised_nf_name = self.network_function_name.lower().replace("_", "-")
224-
return f"{sanitised_nf_name}-acr-manifest-{self.nsd_version.replace('.', '-')}"
232+
sanitised_nf_name = self.network_function_name.lower().replace('_', '-')
233+
return (
234+
f"{sanitised_nf_name}-nsd-acr-manifest-{self.nsd_version.replace('.', '-')}"
235+
)
225236

226237
@property
227238
def nfvi_site_name(self) -> str:
@@ -246,7 +257,7 @@ def arm_template(self) -> ArtifactConfig:
246257
@property
247258
def arm_template_artifact_name(self) -> str:
248259
"""Return the artifact name for the ARM template."""
249-
return f"{self.network_function_definition_group_name}_nfd_artifact"
260+
return f"{self.network_function_definition_group_name}-nfd-artifact"
250261

251262

252263
@dataclass
@@ -337,6 +348,7 @@ class HelmPackageConfig:
337348
@dataclass
338349
class CNFConfiguration(NFConfiguration):
339350
source_registry_id: str = DESCRIPTION_MAP["source_registry_id"]
351+
source_registry_namespace: str = DESCRIPTION_MAP["source_registry_namespace"]
340352
helm_packages: List[Any] = field(default_factory=lambda: [HelmPackageConfig()])
341353

342354
def __post_init__(self):
@@ -354,6 +366,20 @@ def build_output_folder_name(self) -> str:
354366
"""Return the local folder for generating the bicep template to."""
355367
return f"{NF_DEFINITION_OUTPUT_BICEP_PREFIX}{self.nf_name}"
356368

369+
def validate(self):
370+
"""Validate the CNF config
371+
372+
:raises ValidationError: If source registry ID doesn't match the regex
373+
"""
374+
if self.source_registry_id == DESCRIPTION_MAP["source_registry_id"]:
375+
# Config has not been filled in. Don't validate.
376+
return
377+
378+
source_registry_match = re.search(SOURCE_ACR_REGEX, self.source_registry_id)
379+
if not source_registry_match or len(source_registry_match.groups()) < 2:
380+
raise ValidationError(
381+
"CNF config has an invalid source registry ID. Please run `az aosm "
382+
"nfd generate-config` to see the valid formats.")
357383

358384
def get_configuration(
359385
configuration_type: str, config_as_dict: Optional[Dict[Any, Any]] = None

src/aosm/azext_aosm/_params.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from argcomplete.completers import FilesCompleter
77
from azure.cli.core import AzCommandsLoader
88

9-
from .util.constants import CNF, VNF
9+
from .util.constants import CNF, VNF, BICEP_PUBLISH, ARTIFACT_UPLOAD
1010

1111

1212
def load_arguments(self: AzCommandsLoader, _):
@@ -17,6 +17,7 @@ def load_arguments(self: AzCommandsLoader, _):
1717
)
1818

1919
definition_type = get_enum_type([VNF, CNF])
20+
skip_steps = get_enum_type([BICEP_PUBLISH, ARTIFACT_UPLOAD])
2021

2122
# Set the argument context so these options are only available when this specific command
2223
# is called.
@@ -109,6 +110,9 @@ def load_arguments(self: AzCommandsLoader, _):
109110
" alternative parameters."
110111
),
111112
)
113+
c.argument(
114+
"skip", arg_type=skip_steps, help="Optional skip steps"
115+
)
112116

113117
with self.argument_context("aosm nsd") as c:
114118
c.argument(
@@ -118,3 +122,6 @@ def load_arguments(self: AzCommandsLoader, _):
118122
completer=FilesCompleter(allowednames="*.json"),
119123
help="The path to the configuration file.",
120124
)
125+
c.argument(
126+
"skip", arg_type=skip_steps, help="Optional skip steps"
127+
)

src/aosm/azext_aosm/custom.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ def publish_definition(
137137
parameters_json_file: Optional[str] = None,
138138
manifest_file: Optional[str] = None,
139139
manifest_parameters_json_file: Optional[str] = None,
140+
skip: Optional[str] = None,
140141
):
141142
"""
142143
Publish a generated definition.
@@ -156,6 +157,7 @@ def publish_definition(
156157
manifests
157158
:param manifest_parameters_json_file: Optional path to an override bicep parameters
158159
file for manifest parameters
160+
:param skip: options to skip, either publish bicep or upload artifacts
159161
"""
160162
print("Publishing definition.")
161163
api_clients = ApiClients(
@@ -175,6 +177,7 @@ def publish_definition(
175177
parameters_json_file=parameters_json_file,
176178
manifest_bicep_path=manifest_file,
177179
manifest_parameters_json_file=manifest_parameters_json_file,
180+
skip=skip
178181
)
179182
elif definition_type == CNF:
180183
deployer = DeployerViaArm(api_clients, config=config)
@@ -184,6 +187,7 @@ def publish_definition(
184187
parameters_json_file=parameters_json_file,
185188
manifest_bicep_path=manifest_file,
186189
manifest_parameters_json_file=manifest_parameters_json_file,
190+
skip=skip
187191
)
188192
else:
189193
raise ValueError(
@@ -328,6 +332,7 @@ def publish_design(
328332
parameters_json_file: Optional[str] = None,
329333
manifest_file: Optional[str] = None,
330334
manifest_parameters_json_file: Optional[str] = None,
335+
skip: Optional[str] = None,
331336
):
332337
"""
333338
Publish a generated design.
@@ -345,6 +350,7 @@ def publish_design(
345350
manifests
346351
:param manifest_parameters_json_file: Optional path to an override bicep parameters
347352
file for manifest parameters
353+
:param skip: options to skip, either publish bicep or upload artifacts
348354
"""
349355

350356
print("Publishing design.")
@@ -363,6 +369,7 @@ def publish_design(
363369
parameters_json_file=parameters_json_file,
364370
manifest_bicep_path=manifest_file,
365371
manifest_parameters_json_file=manifest_parameters_json_file,
372+
skip=skip
366373
)
367374

368375

src/aosm/azext_aosm/deploy/artifact.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55
"""A module to handle interacting with artifacts."""
66
import subprocess
77
from dataclasses import dataclass
8-
from typing import Union
8+
from typing import Union, List
99

1010
from azure.cli.core.commands import LongRunningOperation
1111
from azure.mgmt.containerregistry.models import ImportImageParameters, ImportSource
1212
from azure.storage.blob import BlobClient, BlobType
1313
from knack.log import get_logger
1414
from knack.util import CLIError
1515
from oras.client import OrasClient
16+
from azure.cli.core.commands import LongRunningOperation
17+
from azure.mgmt.containerregistry import ContainerRegistryManagementClient
1618

1719
from azext_aosm._configuration import ArtifactConfig, HelmPackageConfig
1820

@@ -82,11 +84,18 @@ def _upload_helm_to_acr(self, artifact_config: HelmPackageConfig) -> None:
8284
login_command = ["az", "acr", "login", "--name", registry_name]
8385
subprocess.run(login_command, check=True)
8486

85-
logger.debug("Uploading %s to %s", chart_path, target_registry)
86-
87-
# helm push "$chart_path" "$target_registry"
88-
push_command = ["helm", "push", chart_path, target_registry]
89-
subprocess.run(push_command, check=True)
87+
try:
88+
logger.debug("Uploading %s to %s", chart_path, target_registry)
89+
90+
# helm push "$chart_path" "$target_registry"
91+
push_command = ["helm", "push", chart_path, target_registry]
92+
subprocess.run(push_command, check=True)
93+
finally:
94+
# If we don't logout from the registry, future Artifact uploads to this ACR
95+
# will fail with an UNAUTHORIZED error. There is no az acr logout command,
96+
# but it is a wrapper around docker, so a call to docker logout will work.
97+
logout_command = ["docker", "logout", registry]
98+
subprocess.run(logout_command, check=True)
9099

91100
def _upload_to_storage_account(self, artifact_config: ArtifactConfig) -> None:
92101
"""
@@ -131,12 +140,13 @@ def _upload_to_storage_account(self, artifact_config: ArtifactConfig) -> None:
131140
@staticmethod
132141
def copy_image(
133142
cli_ctx,
134-
container_registry_client,
135-
source_registry_id,
136-
source_image,
137-
target_registry_resource_group_name,
138-
target_registry_name,
139-
mode="NoForce",
143+
container_registry_client: ContainerRegistryManagementClient,
144+
source_registry_id: str,
145+
source_image: str,
146+
target_registry_resource_group_name: str,
147+
target_registry_name: str,
148+
target_tags: List[str],
149+
mode: str = "NoForce",
140150
):
141151
"""
142152
Copy image from one ACR to another.
@@ -147,9 +157,10 @@ def copy_image(
147157
:param source_image: source image
148158
:param target_registry_resource_group_name: target registry resource group name
149159
:param target_registry_name: target registry name
160+
:param target_tags: the list of tags to be applied to the imported image
161+
should be of form: namepace/name:tag or name:tag
150162
:param mode: mode for import
151163
"""
152-
target_tags = [source_image]
153164

154165
source = ImportSource(resource_id=source_registry_id, source_image=source_image)
155166

0 commit comments

Comments
 (0)