Skip to content

Direct access to "models" is deprecated

Laurent Mazuel edited this page Oct 31, 2018 · 3 revisions

Disclaimer

If you are just using public Azure, and not Azure Stack or sovereign cloud (China, Government, etc.) importing from models will still work as expected. But this syntax will ONLY works on public Azure, where new syntax is portable whatever the cloud used.

What is the problem then?

Starting azure-mgmt-compute 4.0.0, Python package are allowed to work on several possible cloud, including public Azure, Azure Stack, or sovereign cloud (China, etc.).

This means this package is able to describe different Rest API version that exists including the latest one and the current one on Azure Stack. Meaning that it's important to understand that the package is wired by default to call public Azure

See this code:

from azure.mgmt.compute import ComputeManagementClient
from azure.mgmt.compute.models import VirtualMachine  # Will implicitly import the model for public Azure (2018-10-01)

client = ComputeManagementClient(**parameters)
client.virtual_machines.create_or_update(  # Will implicitly call the operation for public Azure (2018-10-01)
  rg_name,
  vm_name,
  VirtualMachine(**vm_parameters)  # Model version matches operation version
)

Then, we could see the following code which tries to configure the client for Azure Stack, is actually incorrect:

from azure.common.profile import KnownProfiles
from azure.mgmt.compute import ComputeManagementClient
from azure.mgmt.compute.models import VirtualMachine  # Will implicitly import the model for public Azure (2018-10-01)

client = ComputeManagementClient(profile=KnownProfiles.v2017_03_09_profile, **parameters)
client.virtual_machines.create_or_update(  # Will implicitly call the operation for API 2016-03-30
  rg_name,
  vm_name,
  VirtualMachine(**vm_parameters)  # ! Model version DOES NOT match operation version !
)

This will create a mismatch between the model we send to Azure, and the API called.

What can I do to fix that ?

There is several ways to fix this issue:

Solution 1 : uses model from operation group

Operation groups (e.g. virtual_machines) are already solved against the right api version. Example:

from azure.mgmt.compute import ComputeManagementClient

client = ComputeManagementClient(**parameters)
client.virtual_machines.create_or_update(
  rg_name,
  vm_name,
  client.virtual_machines.models.VirtualMachine(**vm_parameters)  # Model version matches operation version
)

Solution 2 : Do not use model at all as input

You can pass a dictionary to any method, that will be translated into the correct class. These two codes are equivalent:

from azure.mgmt.resource import ResourceManagememtClient
from azure.mgmt.resource.resources.models import ResourceGroup

client = ResourceManagememtClient(**parameters)
client.resource_groups.create_or_update(
  rg_name,
  ResourceGroup(location='westus')
)

and

from azure.mgmt.resource import ResourceManagememtClient

client = ResourceManagememtClient(**parameters)
client.resource_groups.create_or_update(
  rg_name,
  {
    'location': 'westus'
  }
)

The second code is actually creating the right model implicitly using this:

ResourceGroup.from_dict(
  {
    'location': 'westus'
  }
)

which means they are validated exactly in the same way, and will provide the exact same exceptions. But the dictionnary syntax allows you to NOT import any models at all, and let the SDK decide how to serialize it.

Clone this wiki locally