Search code examples
azureazure-devopsazure-powershellazure-devops-self-hosted-agent

Azure and AzureRM Powershell Module Conflicts


I'm setting up an Azure DevOps self hosted pipeline agent. We have some legacy cloud services, so we need the "old" Azure powershell module that targets the service management API. We also obviously use Azure Resource Manager, so either the AzureRM or the new Az module is also required.

We currently have the Azure module version 5.3.0 and AzureRM module version 6.13.1 being installed using the following commands:

Install-Module -Name Azure -RequiredVersion 5.3.0 -AllowClobber -Scope AllUsers -Force
Install-Module -Name AzureRM -RequiredVersion 6.13.1 -AllowClobber -Scope AllUsers -Force

The problem we're encountering is that, depending on the order these modules are imported, we will get script failures. If, for example, the order of import is Azure followed by AzureRM, we get the following error:

Import-Module : The following error occurred while loading the extended type data file: Error in TypeData "Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer": The TypeConverter was ignored because it already occurs. Error in TypeData "Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer": The member SerializationDepth is already present. Error in TypeData "Microsoft.Azure.Commands.Common.Authentication.ProtectedFileTokenCache": The member PropertySerializationSet is already present. Error in TypeData "Microsoft.Azure.Commands.Common.Authentication.ProtectedFileTokenCache": The member SerializationMethod is already present. Error in TypeData "Microsoft.Azure.Commands.Common.Authentication.AuthenticationStoreTokenCache": The member PropertySerializationSet is already present. Error in TypeData "Microsoft.Azure.Commands.Common.Authentication.AuthenticationStoreTokenCache": The member SerializationMethod is already present. Error in TypeData "Microsoft.Azure.Commands.Profile.Models.PSAzureContext": The member SerializationDepth is already present. Error in TypeData "Microsoft.Azure.Commands.Profile.Models.PSAzureProfile": The member SerializationDepth is already present. At C:\Program Files\WindowsPowerShell\Modules\AzureRm\6.13.1\AzureRM.psm1:81 char:1 + Import-Module AzureRM.Profile -RequiredVersion 5.8.2 -Global + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [Import-Module], RuntimeException + FullyQualifiedErrorId : FormatXmlUpdateException,Microsoft.PowerShell.Commands.ImportModuleCommand

You can see this in the following screen shot:

Import Failure

But if import AzureRm first, followed by Azure, it appears to work fine:

Import Success

The problem is, we don't control the order of the imports when using existing pipeline tasks built by Microsoft and others. We're getting failures deploying our cloud services due to the fact the cloud service deployment task built by MS happens to import Azure first.

Lastly, I tried simply not installing the old Azure module, hoping that AzureRM "came with" what it would need to handle some service management API tasks, but it does not. If I try do a deployment without the Azure module installed, we get the error:

Certificate based authentication is not supported. Azure PowerShell module is not found.

So it appears the legacy module is required, and yet it conflicts.


Solution

  • This appears to be caused by the order of installation. Flipping the order from Azure then AzureRm to AzureRm then Azure resolved the issue. So the following install commands do not result in the problem:

    Install-Module -Name AzureRM -RequiredVersion 6.13.1 -AllowClobber -Scope AllUsers -Force
    Install-Module -Name Azure -RequiredVersion 5.3.0 -AllowClobber -Scope AllUsers -Force
    

    It appears the root cause is that the Azure module, if installed first, will always install the most recent version of AzureRm.profile. This appears to be caused by the Azure.Storage module, which has a dependency on AzureRm.profile.

    If you install the Azure module first, it will install AzureRm.profile version 5.8.3. When you then install AzureRm, it has a dependency of AzureRm.profile as well, but it will ignore the fact that you already have AzureRm.profile v5.8.3 installed and install AzureRm.profile v5.8.2. I believe this is because while the Azure module has a dependency on AzureRm.profile, the AzureRm module includes AzureRm.profile.

    When Import-Module is called for Azure first, it loads v5.8.3 of the AzureRm.profile module, as it will always load the most recent version by design. When, however, AzureRm itself is loaded, it tries to load the version IT came with (v5.8.2), and this fails due to the type error noted in the question.

    If you install AzureRM before Azure, it prevents this from happening. Since when the Azure module is being installed it sees there is already a version of AzureRm.profile that satisfies its dependency (or, more specifically, satisfies the dependency that Azure.Storage has), it doesn't install AzureRm.profile again. This leaves only the version that AzureRm was packaged with, and everything is fine.

    Lastly, for an existing "broken" environment, running this command resolved the problem:

    Uninstall-Module -Name AzureRM.profile -RequiredVersion 5.8.3