Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jl/nsd publish paths #139

Merged
merged 15 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/aosm/azext_aosm/build_processors/arm_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def get_artifact_manifest_list(self) -> List[ManifestArtifactFormat]:
:return: A list of artifacts for the artifact manifest.
:rtype: List[ManifestArtifactFormat]
"""
logger.info("Getting artifact manifest list for ARM template input.")
logger.debug("Getting artifact manifest list for ARM template input %s.", self.name)
return [
ManifestArtifactFormat(
artifact_name=self.input_artifact.artifact_name,
Expand Down
2 changes: 2 additions & 0 deletions src/aosm/azext_aosm/build_processors/base_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,4 +200,6 @@ def generate_values_mappings(
default_subschema_values = values[subschema_name] or {}
values[subschema_name] = self.generate_values_mappings(subschema, default_subschema_values, is_ret)

logger.debug("Output of generate_values_mappings for %s: %s", self.name, json.dumps(values, indent=4))

return values
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def get_artifact_manifest_list(self) -> List[ManifestArtifactFormat]:
:return: A list of artifacts for the artifact manifest.
:rtype: List[ManifestArtifactFormat]
"""
logger.info("Getting artifact manifest list for Helm chart input.")
logger.debug("Getting artifact manifest list for Helm chart input %s.", self.name)
artifact_manifest_list = []
artifact_manifest_list.append(
ManifestArtifactFormat(
Expand Down Expand Up @@ -99,7 +99,7 @@ def get_artifact_details(
:return: A tuple containing the list of artifacts and the list of local file builders.
:rtype: Tuple[List[BaseACRArtifact], List[LocalFileBuilder]]
"""
logger.info("Getting artifact details for Helm chart input.")
logger.debug("Getting artifact details for Helm chart input %s.", self.name)
artifact_details: List[BaseArtifact] = []

# We only support local file artifacts for Helm charts
Expand Down Expand Up @@ -141,7 +141,7 @@ def generate_nf_application(self) -> AzureArcKubernetesHelmApplication:
:return: The generated Azure Arc Kubernetes Helm application.
:rtype: AzureArcKubernetesHelmApplication
"""
logger.info("Generating NF application for Helm chart input.")
logger.debug("Generating NF application for Helm chart input %s.", self.name)
artifact_profile = self._generate_artifact_profile()
# We want to remove the registry values paths and image pull secrets values paths from the values mappings
# as these values are supplied by NFM when it installs the chart.
Expand Down
50 changes: 47 additions & 3 deletions src/aosm/azext_aosm/build_processors/nfd_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@

import json
from pathlib import Path
from typing import List, Tuple

from typing import List, Tuple, Any, Dict
from knack.log import get_logger

from azext_aosm.build_processors.base_processor import BaseInputProcessor
Expand Down Expand Up @@ -55,7 +54,7 @@ def get_artifact_manifest_list(self) -> List[ManifestArtifactFormat]:
:return: A list of artifacts for the artifact manifest.
:rtype: List[ManifestArtifactFormat]
"""
logger.info("Getting artifact manifest list for NFD input.")
logger.debug("Getting artifact manifest list for NFD input %s.", self.name)
return [
ManifestArtifactFormat(
artifact_name=self.input_artifact.artifact_name,
Expand Down Expand Up @@ -129,3 +128,48 @@ def generate_resource_element_template(self) -> NFDResourceElementTemplate:
depends_on_profile=DependsOnProfile(install_depends_on=[],
uninstall_depends_on=[], update_depends_on=[]),
)

def _generate_schema(
self,
schema: Dict[str, Any],
source_schema: Dict[str, Any],
values: Dict[str, Any],
) -> None:
"""
Generate the parameter schema.

This function recursively generates the parameter schema for the input artifact by updating
the schema parameter.

:param schema: The schema to generate.
:type schema: Dict[str, Any]
:param source_schema: The source schema.
:type source_schema: Dict[str, Any]
:param values: The values to generate the schema from.
:type values: Dict[str, Any]
"""
if "properties" not in source_schema.keys():
return

# Loop through each property in the schema.
for k, v in source_schema["properties"].items():
# If the property is not in the values, and is required, add it to the values.
# Temp fix for removing schema from deployParameters
if k == "deploymentParameters":
del v["items"]["$schema"]
del v["items"]["title"]
if (
"required" in source_schema
and k not in values
and k in source_schema["required"]
):
if v["type"] == "object":
print(f"Resolving object {k} for schema")
self._generate_schema(schema, v, {})
else:
schema["required"].append(k)
schema["properties"][k] = v
# If the property is in the values, and is an object, generate the values mappings
# for the subschema.
if k in values and v["type"] == "object" and values[k]:
self._generate_schema(schema, v, values[k])
2 changes: 1 addition & 1 deletion src/aosm/azext_aosm/build_processors/vhd_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def get_artifact_manifest_list(self) -> List[ManifestArtifactFormat]:
:return: A list of artifacts for the artifact manifest.
:rtype: List[ManifestArtifactFormat]
"""
logger.info("Getting artifact manifest list for VHD input.")
logger.debug("Getting artifact manifest list for VHD input %s.", self.name)
return [
ManifestArtifactFormat(
artifact_name=self.input_artifact.artifact_name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def _get_processor_list(self) -> [HelmChartProcessor]:
)
else:
raise FileNotFoundError(
"There is no file at the path provided for the mappings file."
f"ERROR: The default values file '{helm_package.default_values}' does not exist"
)
else:
provided_config = None
Expand Down
15 changes: 11 additions & 4 deletions src/aosm/azext_aosm/cli_handlers/onboarding_nsd_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,19 @@ def _get_processor_list(self):
AzureCoreArmBuildProcessor(arm_input.artifact_name, arm_input)
)
elif resource_element.resource_element_type == "NF":
# TODO: change artifact name and version to the nfd name and version or justify why it was this in the first place
# TODO: change artifact name and version to the nfd name and version or justify why it was this in the first place
# AC4 note: I couldn't find a reference in the old code, but this
# does ring a bell. Was it so the artifact manifest didn't get broken with changes to NF versions? I.e., you could make an NF version change in CGV, and the artifact manifest, which is immutable, would still be valid?
# I am concerned that if we have multiple NFs we will have clashing artifact names.
# I'm not changing the behaviour right now as it's too high risk, but we should look again here.
nfdv_object = self._get_nfdv(resource_element.properties)
nfd_input = NFDInput(
# This would be the alternative if we swap from nsd name/version to nfd.
# artifact_name=resource_element.properties.name,
# artifact_version=resource_element.properties.version,
artifact_name=self.config.nsd_name,
artifact_version=self.config.nsd_version,
default_config=None,
default_config={"location": self.config.location},
network_function_definition=nfdv_object,
arm_template_output_path=Path(
NSD_OUTPUT_FOLDER_FILENAME,
Expand Down Expand Up @@ -242,8 +249,8 @@ def build_all_parameters_json(self):
"publisherResourceGroupName": self.config.publisher_resource_group_name,
"acrArtifactStoreName": self.config.acr_artifact_store_name,
"acrManifestName": self.config.acr_artifact_store_name + "-manifest",
"nsDesignGroup":self.config.nsd_name,
"nsDesignVersion" : self.config.nsd_version,
"nsDesignGroup": self.config.nsd_name,
"nsDesignVersion": self.config.nsd_version,
"nfviSiteName": self.nfvi_site_name
}
base_file = JSONDefinitionElementBuilder(
Expand Down
32 changes: 29 additions & 3 deletions src/aosm/azext_aosm/common/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
from azext_aosm.vendored_sdks.models import ManifestArtifactFormat
from azext_aosm.vendored_sdks import HybridNetworkManagementClient
from azext_aosm.common.command_context import CommandContext
from azext_aosm.common.utils import convert_bicep_to_arm
from azext_aosm.configuration_models.common_parameters_config import BaseCommonParametersConfig, VNFCommonParametersConfig
from azext_aosm.vendored_sdks import HybridNetworkManagementClient
from knack.util import CLIError
from knack.log import get_logger
from oras.client import OrasClient



logger = get_logger(__name__)


Expand Down Expand Up @@ -144,13 +147,36 @@ class LocalFileACRArtifact(BaseACRArtifact):

def __init__(self, artifact_name, artifact_type, artifact_version, file_path: Path):
super().__init__(artifact_name, artifact_type, artifact_version)
self.file_path = str(file_path) # TODO: Jordan cast this to str here, check output file isn't broken, and/or is it used as a Path elsewhere?
self.file_path = file_path

# TODO (WIBNI): check if the artifact name ends in .bicep and if so use utils.convert_bicep_to_arm()
# This way we can support in-place Bicep artifacts in the folder.
def upload(self, config: BaseCommonParametersConfig, command_context: CommandContext):
"""Upload the artifact."""
logger.debug("LocalFileACRArtifact config: %s", config)

# TODO: remove, this is temporary until we fix in artifact reader
self.file_path = Path(self.file_path)
# For NSDs, we provide paths relative to the artifacts folder, resolve them to absolute paths
if not self.file_path.is_absolute():
output_folder_path = command_context.cli_options["definition_folder"]
resolved_file_path = output_folder_path.resolve()
upload_file_path = resolved_file_path / self.file_path
print("nfp", output_folder_path)
print("rfp", resolved_file_path)
print("ufp", upload_file_path)
self.file_path = upload_file_path

# self.file_path = Path(self.file_path).resolve()
print("fp", self.file_path)

if self.file_path.suffix == ".bicep":
# Uploading the nf_template as part of the NSD will use this code path
# This does mean we can never have a bicep file as an artifact, but that should be OK
logger.debug("Converting self.file_path to ARM")
arm_template = convert_bicep_to_arm(self.file_path)
self.file_path = self.file_path.with_suffix(".json")
json.dump(arm_template, self.file_path.open("w"))
logger.debug("Converted bicep file to ARM as: %s", self.file_path)

manifest_credentials = self._manifest_credentials(config=config, aosm_client=command_context.aosm_client)
oras_client = self._get_oras_client(manifest_credentials=manifest_credentials)
target_acr = self._get_acr(oras_client)
Expand Down
11 changes: 5 additions & 6 deletions src/aosm/azext_aosm/configuration_models/common_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,17 @@ class ArmTemplatePropertiesConfig:
"""ARM template configuration."""

artifact_name: str = field(
default="", metadata={"comment": "Name of the artifact."}
default="", metadata={"comment": "Name of the artifact. Used as internal reference only."}
)
version: str = field(
default="", metadata={"comment": "Version of the artifact in A.B.C format."}
default="", metadata={"comment": "Version of the artifact in 1.1.1 format."}
)
file_path: str = field(
default="",
metadata={
"comment": (
"File path of the artifact you wish to upload from your local disk.\n"
"Relative paths are relative to the configuration file. "
"On Windows escape any backslash with another backslash."
"File path (absolute or relative to this configuration file) of the artifact you wish to upload from your local disk.\n"
"Use Linux slash (/) file separator even if running on Windows."
)
},
)
Expand All @@ -39,7 +38,7 @@ def validate(self):
if "." not in self.version or "-" in self.version:
raise ValidationError(
"Config validation error. ARM template artifact version should be in"
" format A.B.C"
" format 1.1.1"
)
if not self.file_path:
raise ValidationError("Artifact file path must be set")
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class OnboardingBaseInputConfig(ABC):
metadata={
"comment": (
"Resource group for the Publisher resource.\n"
"You should create this before running the publish command"
"You should create this before running the publish command."
)
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,18 @@ class HelmPackageConfig:
default="",
metadata={
"comment": (
"The file path of Helm Chart on the local disk. Accepts .tgz, .tar or .tar.gz.\n"
"Use Linux slash (/) file separator even if running on Windows."
"The file path to the helm chart on the local disk, relative to the directory from which the command is run.\n"
"Accepts .tgz, .tar or .tar.gz, or an unpacked directory. Use Linux slash (/) file separator even if running on Windows."
)
},
)
default_values: str | None = field(
default="",
metadata={
"comment": (
"The file path (absolute or relative to input.json) of YAML values file on the local disk which "
"The file path (absolute or relative to this configuration file) of YAML values file on the local disk which "
"will be used instead of the values.yaml file present in the helm chart.\n"
"Accepts .yaml or .yml. If left as a blank string, "
"a value mappings file is generated with every value mapped to a deployment parameter.\n"
"Use a blank string and --interactive on the build command to interactively choose which values to map."
"Accepts .yaml or .yml. Use Linux slash (/) file separator even if running on Windows."
)
},
)
Expand Down Expand Up @@ -97,7 +95,7 @@ class OnboardingCNFInputConfig(OnboardingNFDBaseInputConfig):
# TODO: Add better comment for images as not a list
images: ImageSourceConfig = field(
default_factory=ImageSourceConfig,
metadata={"comment": "Source of images to be included in the CNF."},
metadata={"comment": "Source of container images to be included in the CNF. Currently only one source is supported."},
)
helm_packages: List[HelmPackageConfig] = field(
default_factory=lambda: [HelmPackageConfig()],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
class OnboardingNFDBaseInputConfig(OnboardingBaseInputConfig):
"""Common input configuration for onboarding NFDs."""

nf_name: str = field(default="", metadata={"comment": "Name of NF definition."})
nf_name: str = field(default="", metadata={"comment": "Name of the network function."})
version: str = field(
default="",
metadata={"comment": "Version of the NF definition in 1.1.1 format."},
metadata={"comment": "Version of the network function definition in 1.1.1 format."},
)

def validate(self):
Expand All @@ -28,7 +28,7 @@ def validate(self):
raise ValidationError("nf_name must be set")
if not self.version:
raise ValidationError("version must be set")
if "-" in self.version or not "." in self.version:
if "-" in self.version or "." not in self.version:
raise ValidationError(
"Config validation error. Version should be in"
" format 1.1.1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,28 @@ class VhdImageConfig:
"""Configuration for a VHD image."""

artifact_name: str = field(
default="", metadata={"comment": "Optional. Name of the artifact."}
default="", metadata={"comment": "Optional. Name of the artifact. Name will be generated if not supplied."}
)
version: str = field(
default="", metadata={"comment": "Version of the artifact in A-B-C format."}
default="", metadata={"comment": "Version of the artifact in A-B-C format. Note the '-' (dash) not '.' (dot)."}
)
file_path: str = field(
default="",
metadata={
"comment": (
"Optional. File path of the artifact you wish to upload from your local disk. "
"Delete if not required.\nRelative paths are relative to the configuration file. "
"On Windows escape any backslash with another backslash."
"Supply either file_path or blob_sas_url, not both.\n
Cyclam marked this conversation as resolved.
Show resolved Hide resolved
"File path (absolute or relative to this configuration file) of the artifact you wish to upload from your local disk.\n"
"Delete if not required. Use Linux slash (/) file separator even if running on Windows."
Cyclam marked this conversation as resolved.
Show resolved Hide resolved
)
},
)
blob_sas_url: str = field(
default="",
metadata={
"comment": (
"Optional. SAS URL of the blob artifact you wish to copy to your Artifact Store.\n"
"Supply either file_path or blob_sas_url, not both.\nSAS URL of the blob artifact you wish to copy to your Artifact Store.\n"
"Delete if not required. "
Cyclam marked this conversation as resolved.
Show resolved Hide resolved
"On Windows escape any backslash with another backslash."
"Use Linux slash (/) file separator even if running on Windows."
)
},
)
Expand Down Expand Up @@ -118,7 +118,7 @@ class OnboardingVNFInputConfig(OnboardingNFDBaseInputConfig):
# TODO: Add better comments
arm_templates: List[ArmTemplatePropertiesConfig] = field(
default_factory=lambda: [ArmTemplatePropertiesConfig()],
metadata={"comment": "ARM template configuration."},
metadata={"comment": "ARM template configuration. The ARM templates given here would deploy a VM if run. They will be used to generate the VNF."},
)

vhd: VhdImageConfig = field(
Expand Down
2 changes: 1 addition & 1 deletion src/aosm/azext_aosm/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def onboard_nfd_publish(

def onboard_nsd_generate_config(output_file: str | None):
"""Generate config file for onboarding NSD."""
handler = OnboardingNSDCLIHandler(output_file)
handler = OnboardingNSDCLIHandler()
handler.generate_config(output_file)


Expand Down
Loading
Loading