Introduction

This article demonstrates how to set up a Windows development system with Python and the Azure SDK for Python.

After my article, Azure – Lock a VM to Prevent Deletion, I wrote the Azure CLI equivalent commands in Python. On the surface that appears to be an easy task. In reality, because of different Azure SDK for Python module versions, I spent hours hunting down strange problems. Microsoft has deprecated some modules, and because those modules were installed on my system, I had these problems. Therefore, I decided to document the procedure to set up a Windows system for Python, PHP, Node.js, Go, and .NET. This article only covers Python. This article does not cover Visual Studio Code, as I use Visual Studio Enterprise which is an entirely different platform for development.

This article includes several example programs that I wrote using the Azure Resource Manager – Management Locks SDK. I had too many unanswered details after writing the article on locking VMs. Knowing how to use the CLI is important, but sometimes the real knowledge comes from using the API or SDK and deploying for different scenarios. To understand the context of the example programs, read these articles that I wrote:

Step 1 – Create a Hyper-V Virtual Machine

This step is optional. For this article, I wanted a clean environment with no remnants of other languages, libraries, or programs.

Configuration:

  • Windows 10 Enterprise – Download ISO Image Link
  • Memory: 4 GB
  • Disk: 127 GB – Dynamically Expanding
  • Generation 2 – UEFI, 64-bit OS
  • Run Windows Update. Repeat until there is no more update available.
  • Create a directory to store the downloads for the next steps. I use C:\Downloads. That makes it easy to delete the downloads, archive, them, etc.
  • Reboot the system one last time.

Step 2 – Install Tools

Select from this list and install your favorite tools:

Step 3 – Install the Azure CLI

The Azure CLI is not required but is very useful. During development, I use the Python class DefaultAzureCredential to authorize my program from the CLI’s authorization (credentials).

Install the Azure CLI from this link:

Install Azure CLI on Windows

Authorize the Azure CLI

  • az login

An alternative is to use a service principal and I will cover that in the next article.

Step 4 – Install Python 3.9

The current version of Python is 3.9.7 released 2021-08-30. I could not find Microsoft comments for version limitations for Python 3.x, so I will install the latest GA version.

  • Go to the Python download page. [link]
  • Download the latest version for your system. The Python site detects your operating system.

Installation Tips:

  • Enable Add Python 3.9 to PATH.
  • Select Customize installation.
  • Enter a short path such as C:\Python39 for Customize install location. This is to prevent long path name problems later.

Step 5 – Create a Python Projects Working Directory

I do not use my home directory for Python projects. Instead, I create a working directory, a project name, a subproject name, and later directories for each program name. Example c:\work\Azure\Python\ResourceManager\ManagementLocks\List-Locks. This makes backups easier to specify and also makes Git Repositories easier to set up.

Step 6 – Create your first Azure SDK Based Program

I will go into detail in Part 2, but this will help you get started quickly.

Create the program directory

Based on the working directory, create a directory named “List-Locks” or similar.

Example:

  • cd c:\work\Azure\Python\ResourceManager\ManagementLocks
  • mkdir List-Locks
  • cd List-Locks

Enable the Python Virtual Environment

The following command will create a directory name env to store the Python virtual environment, create the environment, and then activate the environment. This is a very important step. There are so many collisions and conflicts with the Azure SDK for Python. This step isolates the environment and installs packages to the program’s working directory.

  •  python -m venv env
  •  env\Scripts\activate

Update the Python PIP program

  • python -m pip install -U pip

Create a requirements.txt file

The file requirements.txt declares the Python packages that are required for a program to operate correctly.

Using your favorite editor, create a file named requirments.txt with the following content:

azure-mgmt-resource>=18.0.0
azure-identity>=1.5.0

Install dependencies

  • pip install -r requirements.txt

Create the program file

Create a file named list_locks.py

##############################################################################
# Date Created: 2021-09-17
# Last Update:  2021-09-17
# https://www.jhanley.com - Google Cloud
# Copyright (c) 2021, John J. Hanley
# Author: John J. Hanley
# License: MIT
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##############################################################################

'''
This program displays the Azure Manage Locks at the subscription level.
'''

# Indents are tabs
# Add this to your .pylintrc
# [FORMAT]
# indent-string="\t"

# Requirements:
# pip install -r requirements.txt

import os
from azure.mgmt.resource import ManagementLockClient
from azure.identity import DefaultAzureCredential

def get_authorization_token():
    '''
    Return an authorization token that is setup by the Azure CLI.
    This requires the credentials created by the command "az login" are valid.
    '''

    credential = DefaultAzureCredential(
        exclude_cli_credential=False,
        exclude_environment_credential=True,
        exclude_managed_identity_credential=True,
        exclude_visual_studio_code_credential=True,
        exclude_shared_token_cache_credential=True
    )

    return credential

def get_resource_name(resource_id):
    '''
    Parse the Resource ID and return the Resource Name
    '''

    parts = resource_id.split('/')

    # print('len: ', len(parts))
    if len(parts) < 9:
        return ''

    return parts[8]

def get_resource_type(resource_id):
    '''
    Parse the Resource ID and return the Resource Type
    '''

    parts = resource_id.split('/')

    # print('len: ', len(parts))
    if len(parts) < 9:
        return ''

    return parts[7]

def display_locks(locks):
    '''
    Display the Azure Management Locks formatted to the screen.
    '''

    # Display a header
    print("{0:<20} {1:<22} {2:<15} {3}".format(
        "Resource Name",
        "Resource Type",
        "Lock Level",
        "Lock Name"))

    print("{0} {1} {2} {3}".format("-"*20, "-"*22, "-"*15, "-"*15))

    for item in locks:
        print(
            "{0:<20} {1:<22} {2:<15} {3}"
            .format(
                get_resource_name(item.id),
                get_resource_type(item.id),
                item.level,
                item.name,
            )
        )

if __name__ == '__main__':
    # Main function.
    # 1) Get the Subscription ID
    # 2) Get authorization credentials
    # 3) Fetch the Azure Management Locks
    # 4) Display lock details

    # Retrieve subscription ID from an environment variable.
    # az account show
    # set AZURE_SUBSCRIPTION_ID=REPACLE_ME
    azure_subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]

    # Get a authorization credentials
    azure_credential = get_authorization_token()

    # Fetch the Azure Management Locks
    # at the subscription level
    client = ManagementLockClient(azure_credential, azure_subscription_id)

    azure_locks = list(client.management_locks.list_at_subscription_level())

    # Display lock details
    display_locks(azure_locks)

Setup environment variable

This step requires the Azure CLI to display the account Subscription ID. This is also available in the Azure Portal.

Run the following command:

  • az account show

The account information is displayed in JSON. Copy the value for “id” without the quotes.

Run the following command to set the environment variable AZURE_SUBSCRIPTION_ID. Replace the text REPLACE_ME with the id from the previous command output.

  • set AZURE_SUBSCRIPTION_ID=REPLACE_ME

Run the program

If there are any Management Locks within the subscription, a formatted table will be displayed.

Run the Python program:

  • python list_locks.py

Example output:

Resource Name        Resource Type          Lock Level      Lock Name
-------------------- ---------------------- --------------- ---------------
jhanley-dev          virtualMachines        CanNotDelete    Prevent-Delete
jhanley-dev-ip       publicIPAddresses      CanNotDelete    Prevent-Delete
home-only            networkSecurityGroups  CanNotDelete    Prevent-Delete

Next Steps

In the next article, I will go into detail about the Azure Resource Manager SDK, Authorization, and how to interface with Azure.

Photography Credits

I write free articles about technology. Recently, I learned about Pexels.com which provides free images. The image in this article is courtesy of Pixabay at Pexels.