Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/sunny/bicep-deployer' into add-c…
Browse files Browse the repository at this point in the history
…nf-generation
  • Loading branch information
jddarby committed May 9, 2023
2 parents cb51f0a + fe87a11 commit 5d3bc12
Show file tree
Hide file tree
Showing 23 changed files with 593 additions and 423 deletions.
57 changes: 57 additions & 0 deletions src/aosm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Microsoft Azure CLI 'aosm' Extension
==========================================

This package is for the 'aosm' extension to support Azure Operator Service Manager
functions.
i.e. `az aosm`

Install via `az extension add --name aosm`


# Background
The `az aosm` extension provides support for publishing Network Function Definitions
to use with Azure Operator Service Manager or Network Function Manager.

# Pre-requisites
## VNFs
For VNFs, you will need a single ARM template which would create the Azure resources
for your VNF, for example a Virtual Machine, disks and NICs. You'll also need a VHD
image that would be used for the VNF Virtual Machine.

# Command examples

Get help on command arguments

`az aosm -h`
`az aosm definition -h`
`az aosm definition build -h`
etc...

All these commands take a `--definition-type` argument of `vnf`, `cnf` or (coming) `nsd`

Create an example config file for building a definition

`az aosm definition generate-config --config-file input.json`

This will output a file called `input.json` which must be filled in.
Once the config file has been filled in the following commands can be run.

Build a definition locally

`az aosm definition build --config-file input.json`

Build and publish a definition

`az aosm definition build --config-file input.json --publish`

Publish a pre-built definition

`az aosm definition publish --config-file input.json`

Delete a published definition

`az aosm definition delete --config-file input.json`

Delete a published definition and the publisher, artifact stores and NFD group

`az aosm definition delete --config-file input.json --clean`
5 changes: 0 additions & 5 deletions src/aosm/README.rst

This file was deleted.

4 changes: 1 addition & 3 deletions src/aosm/azext_aosm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ def __init__(self, cli_ctx=None):
from azure.cli.core.commands import CliCommandType

aosm_custom = CliCommandType(operations_tmpl="azext_aosm.custom#{}")
super(AosmCommandsLoader, self).__init__(
cli_ctx=cli_ctx, custom_command_type=aosm_custom
)
super().__init__(cli_ctx=cli_ctx, custom_command_type=aosm_custom)

def load_command_table(self, args):
from azext_aosm.commands import load_command_table
Expand Down
107 changes: 72 additions & 35 deletions src/aosm/azext_aosm/_configuration.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,53 @@
from dataclasses import dataclass, field
from typing import Optional, Any, List
from typing import Dict, Optional, Any, List
from pathlib import Path
from azure.cli.core.azclierror import ValidationError, InvalidArgumentValueError
from ._constants import VNF, CNF, NSD
from azext_aosm.util.constants import VNF_DEFINITION_OUTPUT_BICEP_PREFIX, VNF, CNF, NSD

DESCRIPTION_MAP: Dict[str, str] = {
"publisher_name": "Name of the Publisher resource you want you definition published to",
"publisher_resource_group_name": "Resource group the Publisher resource is in or you want it to be in",
"nf_name": "Name of NF definition",
"version": "Version of the NF definition",
"acr_artifact_store_name": "Name of the ACR Artifact Store resource",
"location": "Azure location of the resources",
"blob_artifact_store_name": "Name of the storage account Artifact Store resource",
"artifact_name": "Name of the artifact",
"file_path": (
"Optional. File path of the artifact you wish to upload from your "
"local disk. Delete if not required."
),
"blob_sas_url": (
"Optional. SAS URL of the blob artifact you wish to copy to your "
"Artifact Store. Delete if not required."
),
"artifact_version": (
"Version of the artifact. For VHDs this must be in format A-B-C. "
"For ARM templates this must be in format A.B.C"
),
}


@dataclass
class ArtifactConfig:
artifact_name: str = "Name of the artifact"
file_path: Optional[
str
] = "File path of the artifact you wish to upload from your local disk"
blob_sas_url: Optional[
str
] = "SAS URL of the blob artifact you wish to copy to your Artifact Store"
version: str = (
"Version of the artifact. For VHDs this must be in format A-B-C. "
"For ARM templates this must be in format A.B.C"
)
artifact_name: str = DESCRIPTION_MAP["artifact_name"]
# artifact.py checks for the presence of the default descriptions, change there if
# you change the descriptions.
file_path: Optional[str] = DESCRIPTION_MAP["file_path"]
blob_sas_url: Optional[str] = DESCRIPTION_MAP["blob_sas_url"]
version: str = DESCRIPTION_MAP["artifact_version"]


@dataclass
class Configuration:
publisher_name: str = (
"Name of the Publisher resource you want you definition published to"
)
publisher_resource_group_name: str = (
"Resource group the Publisher resource is in or you want it to be in"
)
nf_name: str = "Name of NF definition"
version: str = "Version of the NF definition"
acr_artifact_store_name: str = "Name of the ACR Artifact Store resource"
location: str = "Azure location of the resources"
publisher_name: str = DESCRIPTION_MAP["publisher_name"]
publisher_resource_group_name: str = DESCRIPTION_MAP[
"publisher_resource_group_name"
]
nf_name: str = DESCRIPTION_MAP["nf_name"]
version: str = DESCRIPTION_MAP["version"]
acr_artifact_store_name: str = DESCRIPTION_MAP["acr_artifact_store_name"]
location: str = DESCRIPTION_MAP["location"]

@property
def nfdg_name(self) -> str:
Expand All @@ -45,23 +62,34 @@ def acr_manifest_name(self) -> str:

@dataclass
class VNFConfiguration(Configuration):
blob_artifact_store_name: str = (
"Name of the storage account Artifact Store resource"
)
blob_artifact_store_name: str = DESCRIPTION_MAP["blob_artifact_store_name"]
arm_template: Any = ArtifactConfig()
vhd: Any = ArtifactConfig()

def __post_init__(self):
"""
Cope with deserializing subclasses from dicts to ArtifactConfig.
Used when creating VNFConfiguration object from a loaded json config file.
"""
if isinstance(self.arm_template, dict):
self.arm_template = ArtifactConfig(**self.arm_template)

if isinstance(self.vhd, dict):
self.vhd = ArtifactConfig(**self.vhd)

@property
def sa_manifest_name(self) -> str:
"""Return the Storage account manifest name from the NFD name."""
return f"{self.nf_name}-sa-manifest-{self.version.replace('.', '-')}"

@property
def build_output_folder_name(self) -> str:
"""Return the local folder for generating the bicep template to."""
arm_template_path = self.arm_template.file_path
return (
f"{VNF_DEFINITION_OUTPUT_BICEP_PREFIX}{Path(str(arm_template_path)).stem}"
)

@dataclass
class HelmPackageConfig:
Expand All @@ -84,8 +112,9 @@ def __post_init__(self):
package = HelmPackageConfig(**dict(package))


def get_configuration(definition_type, config_as_dict=None) -> Configuration:

def get_configuration(
definition_type: str, config_as_dict: Optional[Dict[Any, Any]] = None
) -> Configuration:
if config_as_dict is None:
config_as_dict = {}

Expand Down Expand Up @@ -119,10 +148,18 @@ def validate_configuration(config: Configuration) -> None:
raise ValidationError(
"Config validation error. VHD artifact version should be in format A-B-C"
)
if (
"." not in config.arm_template.version
or "-" in config.arm_template.version
):
if "." not in config.arm_template.version or "-" in config.arm_template.version:
raise ValidationError(
"Config validation error. ARM template artifact version should be in format A.B.C"
)

if not (
(config.vhd.file_path or config.vhd.blob_sas_url)
or (
config.vhd.file_path == DESCRIPTION_MAP["file_path"]
and config.vhd.blob_sas_url == DESCRIPTION_MAP["blob_sas_url"]
)
):
raise ValidationError(
"Config validation error. VHD config must have either a local filepath or a blob SAS URL"
)
12 changes: 10 additions & 2 deletions src/aosm/azext_aosm/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
short-summary: Manage AOSM publisher definitions.
"""

helps[
"aosm definition generate-config"
] = """
type: command
short-summary: Generate configuration file for building an AOSM publisher definition.
"""

helps[
"aosm definition build"
] = """
Expand All @@ -29,12 +36,13 @@
"""

helps[
"aosm definition generate-config"
"aosm definition publish"
] = """
type: command
short-summary: Generate configuration file for building an AOSM publisher definition.
short-summary: Publish a pre-built AOSM publisher definition.
"""


helps[
"aosm definition delete"
] = """
Expand Down
33 changes: 31 additions & 2 deletions src/aosm/azext_aosm/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

from argcomplete.completers import FilesCompleter
from azure.cli.core import AzCommandsLoader
#from knack.arguments import CLIArgumentType
from ._constants import VNF, CNF, NSD

# from knack.arguments import CLIArgumentType
from .util.constants import VNF, CNF, NSD


def load_arguments(self: AzCommandsLoader, _):
Expand Down Expand Up @@ -42,6 +43,34 @@ def load_arguments(self: AzCommandsLoader, _):
arg_type=get_three_state_flag(),
help="Also delete artifact stores, NFD Group and Publisher. Use with care.",
)
c.argument(
"definition_file",
options_list=["--definition-file", "-b"],
type=file_type,
completer=FilesCompleter(allowednames="*.json"),
help="Optional path to a bicep file to publish. Use to override publish of the built definition with an alternative file.",
)
c.argument(
"parameters_json_file",
options_list=["--parameters-file", "-p"],
type=file_type,
completer=FilesCompleter(allowednames="*.json"),
help="Optional path to a parameters file for the bicep definition file. Use to override publish of the built definition and config with alternative parameters.",
)
c.argument(
"manifest_file",
options_list=["--manifest-file", "-m"],
type=file_type,
completer=FilesCompleter(allowednames="*.json"),
help="Optional path to a bicep file to publish manifests. Use to override publish of the built definition with an alternative file.",
)
c.argument(
"manifest_parameters_json_file",
options_list=["--manifest-parameters-file", "-mp"],
type=file_type,
completer=FilesCompleter(allowednames="*.json"),
help="Optional path to a parameters file for the manifest definition file. Use to override publish of the built definition and config with alternative parameters.",
)

with self.argument_context("aosm generate-config") as c:
c.argument(
Expand Down
4 changes: 3 additions & 1 deletion src/aosm/azext_aosm/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

# pylint: disable=line-too-long
from azure.cli.core import AzCommandsLoader
#from azure.cli.core.commands import CliCommandType

# from azure.cli.core.commands import CliCommandType
from azext_aosm._client_factory import cf_aosm


Expand All @@ -21,6 +22,7 @@ def load_command_table(self: AzCommandsLoader, _):
g.custom_command("build", "build_definition")
g.custom_command("delete", "delete_published_definition")
g.custom_command("show", "show_publisher")
g.custom_command("publish", "publish_definition")

with self.command_group("aosm", is_preview=True):
pass
Loading

0 comments on commit 5d3bc12

Please sign in to comment.