Skip to content

Commit

Permalink
Merge pull request #18 from release-engineering/azure1p
Browse files Browse the repository at this point in the history
Azure: Support coreVirtualMachine publishing
  • Loading branch information
JAVGan authored Sep 13, 2024
2 parents cc33b85 + ede4f0f commit 02b4a05
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 6 deletions.
54 changes: 54 additions & 0 deletions cloudpub/models/ms_azure.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
import sys
from enum import Enum
from typing import Any, Dict, List, Optional

if sys.version_info >= (3, 8):
Expand Down Expand Up @@ -1419,6 +1420,9 @@ class VMIProperties(AttrsJSONDecodeMixin):
.. _See the docs: https://learn.microsoft.com/en-us/azure/marketplace/azure-vm-plan-technical-configuration#properties
""" # noqa E501

networkVirtualAppliance: bool = field(default=False, metadata={"hide_unset": True})
"""Boolean indicating the network virtual appliance support for core machines."""

supportsNVMe: bool = field(default=False, metadata={"hide_unset": True})
"""
Boolean indicating the NVMe support. `See the docs`_ for more details.
Expand Down Expand Up @@ -1462,6 +1466,18 @@ class VMIProperties(AttrsJSONDecodeMixin):
.. _See the docs: https://learn.microsoft.com/en-us/azure/marketplace/azure-vm-plan-technical-configuration#properties
""" # noqa E501

availableToFreeAccounts: bool = field(default=False, metadata={"hide_unset": True})
"""Boolean indicating whether image is available for free accounts."""

supportsClientHub: bool = field(default=False, metadata={"hide_unset": True})
"""Boolean indicating whether image supports the client hub."""

supportsHubOnOffSwitch: bool = field(default=False, metadata={"hide_unset": True})
"""Boolean indicating whether image supports the on/off switch."""

supportsSriov: bool = field(default=False, metadata={"hide_unset": True})
"""Boolean indicating whether image supports SR-IOV."""


@define
class VMISku(AttrsJSONDecodeMixin):
Expand Down Expand Up @@ -1684,6 +1700,43 @@ def base_plan_id(self) -> Optional[str]:
return None


class SoftwareType(str, Enum):
"""Define the ``SoftwareType`` enum for :class:`~cloudpub.models.ms_azure.CoreVMIPlanTechConfig`.""" # noqa: E501

operating_system = "operatingSystem"
solution = "solution"

def __str__(self) -> str:
return self.value


@define
class CoreVMIPlanTechConfig(VMIPlanTechConfig):
"""
Represent the Core VM technical configuration of a Plan.
`Schema definition for VMIPlanTechConfig <https://schema.mp.microsoft.com/schema/core-virtual-machine-plan-technical-configuration/2022-03-01-preview5>`_
""" # noqa E501

schema: str = field(
validator=instance_of(str),
metadata={
"alias": MS_SCHEMA,
"const": "https://schema.mp.microsoft.com/schema/core-virtual-machine-plan-technical-configuration/2022-03-01-preview5", # noqa E501
},
)
"""
The `resource schema`_ for Graph API.
.. _resource schema: https://learn.microsoft.com/en-us/azure/marketplace/product-ingestion-api#resource-api-reference
""" # noqa E501

software_type: SoftwareType = field(
default=SoftwareType.operating_system,
metadata={"alias": "softwareType"},
)


RESOURCE_MAPING = {
"product": ProductSummary,
"customer-leads": CustomerLeads,
Expand All @@ -1697,6 +1750,7 @@ def base_plan_id(self) -> Optional[str]:
"price-and-availability-offer": PriceAndAvailabilityOffer,
"price-and-availability-plan": PriceAndAvailabilityPlan,
"virtual-machine-plan-technical-configuration": VMIPlanTechConfig,
"core-virtual-machine-plan-technical-configuration": CoreVMIPlanTechConfig,
"reseller": ProductReseller,
"submission": ProductSubmission,
}
Expand Down
10 changes: 6 additions & 4 deletions cloudpub/ms_azure/service.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import json
import logging
import os
from typing import Any, Dict, Iterator, List, Optional, Tuple, Union, cast
Expand Down Expand Up @@ -102,11 +103,12 @@ def _configure(self, data: Dict[str, Any]) -> ConfigureStatus:
Returns:
The job ID to track its status alongside the initial status.
"""
log.debug("Received the following data to create/modify: %s" % data)
log.debug("Received the following data to create/modify: %s" % json.dumps(data, indent=2))
resp = self.session.post(path="configure", json=data)
self._raise_for_status(response=resp)
parsed_resp = ConfigureStatus.from_json(resp.json())
log.debug("Create/modify request response: %s", parsed_resp)
rsp_data = resp.json()
log.debug("Create/modify request response: %s", rsp_data)
parsed_resp = ConfigureStatus.from_json(rsp_data)
return parsed_resp

def _query_job_details(self, job_id: str) -> ConfigureStatus:
Expand Down Expand Up @@ -192,7 +194,7 @@ def configure(self, resource: AzureResource) -> ConfigureStatus:
"$schema": self.CONFIGURE_SCHEMA.format(AZURE_API_VERSION=self.AZURE_API_VERSION),
"resources": [resource.to_json()],
}
log.debug("Data to configure: %s", data)
log.info("Data to configure: %s", json.dumps(data, indent=2))
res = self._configure(data=data)
return self._wait_for_job_completion(job_id=res.job_id)

Expand Down
12 changes: 12 additions & 0 deletions tests/ms_azure/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,18 @@ def technical_config(disk_version: Dict[str, Any]) -> Dict[str, Any]:
}


@pytest.fixture
def core_technical_config(technical_config: Dict[str, Any]) -> Dict[str, Any]:
technical_config.update(
{
"$schema": "https://schema.mp.microsoft.com/schema/core-virtual-machine-plan-technical-configuration/2022-03-01-preview5", # noqa: E501
"id": "core-virtual-machine-plan-technical-configuration/ffffffff-ffff-ffff-ffff-ffffffffffff/00000000-0000-0000-0000-000000000000", # noqa: E501
"softwareType": "operatingSystem",
}
)
return technical_config


@pytest.fixture
def reseller() -> Dict[str, Any]:
return {
Expand Down
24 changes: 24 additions & 0 deletions tests/ms_azure/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pytest

from cloudpub.models.ms_azure import (
CoreVMIPlanTechConfig,
CustomerLeads,
DeprecationAlternative,
DeprecationSchedule,
Expand All @@ -13,6 +14,7 @@
PlanSummary,
Product,
PublishTarget,
SoftwareType,
VMImageSource,
VMIPlanTechConfig,
VMISku,
Expand Down Expand Up @@ -125,6 +127,28 @@ def test_vmi_plan_tech_config_property(technical_config: Dict[str, Any]) -> None
assert obj.base_plan_id == plan_id


def test_vmi_plan_tech_config_properties(core_technical_config: Dict[str, Any]) -> None:
# Test base_plan_id not set
obj = CoreVMIPlanTechConfig.from_json(core_technical_config)

assert obj.base_plan_id is None

# Test base_plan_id set
plan_id = "00000000-0000-0000-0000-000000000000"
plan_durable = f"plan/ffffffff-ffff-ffff-ffff-ffffffffffff/{plan_id}"
core_technical_config.update({"basePlan": plan_durable})

obj = CoreVMIPlanTechConfig.from_json(core_technical_config)

assert obj.base_plan_id == plan_id


@pytest.mark.parametrize("software_type", ["operatingSystem", "solution"])
def test_software_type_render_str(software_type: str) -> None:
s = SoftwareType(software_type)
assert str(s) == software_type


def test_deprecation_schedule_defaults() -> None:
"""Test the default values for DeprecationSchedule."""
data = {
Expand Down
8 changes: 6 additions & 2 deletions tests/ms_azure/test_service.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import logging
from copy import deepcopy
from typing import Any, Dict, List
Expand Down Expand Up @@ -139,7 +140,10 @@ def test_configure_request(
mock_post.assert_called_once_with(path="configure", json=req_json)
mock_raise_status.assert_called_once_with(response=res_obj)
assert res == ConfigureStatus.from_json(res_json)
assert f"Received the following data to create/modify: {req_json}" in caplog.text
assert (
f"Received the following data to create/modify: {json.dumps(req_json, indent=2)}" # noqa: E501
in caplog.text
)

@mock.patch("cloudpub.ms_azure.AzureService._raise_for_status")
def test_query_job_details(
Expand Down Expand Up @@ -262,7 +266,7 @@ def test_configure(

mock_configure.assert_called_once_with(data=expected_data)
mock_wait_completion.assert_called_once_with(job_id=job_id)
assert f"Data to configure: {expected_data}" in caplog.text
assert f"Data to configure: {json.dumps(expected_data, indent=2)}" in caplog.text

@mock.patch("cloudpub.ms_azure.AzureService._raise_error")
@mock.patch("cloudpub.ms_azure.AzureService._assert_dict")
Expand Down

0 comments on commit 02b4a05

Please sign in to comment.