Skip to content

Direct access to "models" is deprecated

annatisch edited this page Oct 31, 2018 · 3 revisions

Disclaimer

If you are only using public Azure, and not Azure Stack or a sovereign cloud (China, Government, etc.), importing from models will still work as expected. But this syntax will now ONLY work on public Azure, whereas the syntax described below is available across all cloud offerings.

What is the problem then?

Starting with azure-mgmt-compute 4.0.0, some Azure SDK Python packages are compatible with several possible cloud offerings, including public Azure, Azure Stack, and sovereign clouds (China, etc.).

This means these packages are able to describe different REST API versions that exist; including the latest one, and the current one on Azure Stack. Therefore it's important to understand that the package is wired by default to call the latest stable public Azure API version.

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
)

Now, let's see the following code which tries to configure the client for Azure Stack, and 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 are several ways to fix this issue:

Solution 1 : Use models from the operation group

Operation groups (e.g. virtual_machines) are already resolved 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 a model as input at all

You can pass a dictionary to any method, and it will be automatically translated into the correct class. These two code snippets 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 snippet is actually creating the right model implicitly using this:

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

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