forked from Azure/azure-cli-extensions
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Draft create NFDV using python SDK * pushing this but then moving on to delete * start to move to bicep deployer * VNF generate and deploy bare bones, not working * predeployer maybe working * Fix up VNF generate and deploy * printing * artifact upload half broken * Artifact manifest stuff over to SDK * delete NFD function * linting * Fix up json config -> VNFConfiguration * artifact manifests separate * style * renames * style * lint and reverse some renames * dev instructions * oops. bad find and replace work. * undo friday afternoon bad changes * manifest optional * Basic README * delete publisher definition * unwanted constant * d * Update src/aosm/setup.py Suggestion from cyclam Co-authored-by: Cyclam <95434717+Cyclam@users.noreply.github.com> * markups * lint --------- Co-authored-by: Cyclam <95434717+Cyclam@users.noreply.github.com>
- Loading branch information
1 parent
8cdf766
commit 057ef05
Showing
30 changed files
with
2,181 additions
and
576 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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` |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,156 @@ | ||
from dataclasses import dataclass | ||
from typing import Optional | ||
from knack.util import CLIError | ||
from ._constants import VNF, CNF, NSD | ||
from typing import Dict, Optional, Any | ||
from pathlib import Path | ||
from azure.cli.core.azclierror import ValidationError, InvalidArgumentValueError | ||
from azext_aosm.util.constants import VNF_DEFINITION_OUTPUT_BICEP_PREFIX, VNF, CNF, NSD | ||
|
||
DESCRIPTION_MAP: Dict[str, str] = { | ||
"publisher_resource_group_name": ( | ||
"Resource group for the Publisher resource. Will be " | ||
"created if it does not exist." | ||
), | ||
"publisher_name": ("Name of the Publisher resource you want your definition " | ||
"published to. Will be created if it does not exist." | ||
), | ||
"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 to use when creating 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" | ||
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" | ||
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" | ||
class NFConfiguration: | ||
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: | ||
"""Return the NFD Group name from the NFD name.""" | ||
return f"{self.nf_name}-nfdg" | ||
|
||
@property | ||
def acr_manifest_name(self) -> str: | ||
"""Return the ACR manifest name from the NFD name.""" | ||
return f"{self.nf_name}-acr-manifest-{self.version.replace('.', '-')}" | ||
|
||
|
||
@dataclass | ||
class VNFConfiguration(Configuration): | ||
blob_artifact_store_name: str = "Name of the storage account Artifact Store resource" | ||
arm_template: ArtifactConfig = ArtifactConfig() | ||
vhd: ArtifactConfig = ArtifactConfig() | ||
class VNFConfiguration(NFConfiguration): | ||
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) | ||
self.validate() | ||
|
||
def validate(self) -> None: | ||
""" | ||
Validate the configuration passed in. | ||
:raises ValidationError for any invalid config | ||
""" | ||
if self.vhd.version == DESCRIPTION_MAP["version"]: | ||
# Config has not been filled in. Don't validate. | ||
return | ||
|
||
if "." in self.vhd.version or "-" not in self.vhd.version: | ||
raise ValidationError( | ||
"Config validation error. VHD artifact version should be in format A-B-C" | ||
) | ||
if "." not in self.arm_template.version or "-" in self.arm_template.version: | ||
raise ValidationError( | ||
"Config validation error. ARM template artifact version should be in format A.B.C" | ||
) | ||
filepath_set = ( | ||
self.vhd.file_path and self.vhd.file_path != DESCRIPTION_MAP["file_path"] | ||
) | ||
sas_set = ( | ||
self.vhd.blob_sas_url | ||
and self.vhd.blob_sas_url != DESCRIPTION_MAP["blob_sas_url"] | ||
) | ||
# If these are the same, either neither is set or both are, both of which are errors | ||
if filepath_set == sas_set: | ||
raise ValidationError( | ||
"Config validation error. VHD config must have either a local filepath or a blob SAS URL" | ||
) | ||
|
||
if filepath_set: | ||
# Explicitly set the blob SAS URL to None to avoid other code having to | ||
# check if the value is the default description | ||
self.vhd.blob_sas_url = None | ||
elif sas_set: | ||
self.vhd.file_path = None | ||
|
||
@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}" | ||
) | ||
|
||
|
||
def get_configuration(definition_type, config_as_dict=None): | ||
def get_configuration( | ||
definition_type: str, config_as_dict: Optional[Dict[Any, Any]] = None | ||
) -> NFConfiguration: | ||
if config_as_dict is None: | ||
config_as_dict = {} | ||
|
||
if definition_type == VNF: | ||
config = VNFConfiguration(**config_as_dict) | ||
elif definition_type == CNF: | ||
config = Configuration(**config_as_dict) | ||
config = NFConfiguration(**config_as_dict) | ||
elif definition_type == NSD: | ||
config = Configuration(**config_as_dict) | ||
config = NFConfiguration(**config_as_dict) | ||
else: | ||
raise CLIError("Definition type not recognized, options are: vnf, cnf or nsd") | ||
raise InvalidArgumentValueError( | ||
"Definition type not recognized, options are: vnf, cnf or nsd" | ||
) | ||
|
||
return config |
Oops, something went wrong.