Skip to content

Commit

Permalink
ACA-1842: Image SKUs support in Ansible collection -
Browse files Browse the repository at this point in the history
Creaing azure_rm_imagesku_info module to get oll of the availble SKU options for VM image.
Creating azure_test_image_skus to test the creation of a vm with an image from the SKU list of options
Updating the test list in the inventory file with azure_test_imageskus test.

Signed-off-by: hyaish <[email protected]>
  • Loading branch information
Yaish25491 committed Sep 19, 2024
1 parent 1fd45ee commit 4a8ca03
Show file tree
Hide file tree
Showing 3 changed files with 328 additions and 0 deletions.
226 changes: 226 additions & 0 deletions plugins/modules/azure_rm_imagesku_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
#!/usr/bin/python
#
# Copyright (c) 2024
# Hen Yaish <[email protected]>
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function

__metaclass__ = type

DOCUMENTATION = '''
---
module: azure_rm_imagesku_info
version_added: "2.4.0"
short_description: Get compute-related Image SKUs list
description:
- Get details for compute-related resource Image SKUs.
options:
location:
description:
- A region supported by current subscription.
type: str
offer:
description:
- The `Offer` refers to the specific product line of the operating system or software.
- The offer usually includes multiple versions or configurations of the product.
type: str
publisher:
description:
- The `Publisher` is the entity that provides the OS image. It could be Microsoft, Canonical (for Ubuntu), Red Hat, etc.
- It is a mandatory field that identifies the provider of the image.
type: str
extends_documentation_fragment:
- azure.azcollection.azure
author:
- Hen Yaish (@hyaish)
'''

EXAMPLES = '''
- name: Gather Resource Group info
azure.azcollection.azure_rm_resourcegroup_info:
name: "{{ resource_group }}"
register: rg_info
- name: List available Image SKUs for 0001-com-ubuntu-server-focal
azure.azcollection.azure_rm_imagesku_info:
location: westus
offer: 0001-com-ubuntu-server-focal
publisher: Canonical
register: available_image_skus_results
'''

RETURN = '''
available_skus:
description:
- List of Azure image SKUs for provisioning virtual machines.
returned: always
type: complex
contains:
name:
description:
- The specific SKU name or version.
returned: always
type: str
sample: "20_04-lts"
id:
description:
- The full Azure resource ID for the SKU.
returned: always
type: str
sample: "0001-com-ubuntu-server-focal/Skus/20_04-lts"
location:
description:
- The Azure region where the SKU is available.
returned: always
type: str
sample: "westus"
automatic_os_upgrade_supported:
description:
- Whether automatic OS upgrades are supported for this SKU.
returned: always
type: bool
sample: false
restrictions:
description:
- Restrictions that may apply to the use of this image SKU, such as region limitations or feature incompatibility.
returned: always
type: complex
contains:
type:
description:
- The type of restriction, which could include location-based restrictions or hardware compatibility issues.
type: str
returned: always
sample: "location"
values:
description:
- A list of restricted locations, regions, or zones where the image SKU cannot be used.
type: list
returned: always
sample: ["eastus", "westeurope"]
reason_code:
description:
- The reason for the restriction, such as quota limitations or specific hardware requirements.
type: str
sample: "NotSupported"
restriction_info:
description:
- Additional information about the restrictions, such as unsupported regions or features.
returned: always
type: complex
contains:
locations:
description:
- Locations where this SKU is restricted or unavailable.
type: list
sample: ["eastus"]
zones:
description:
- Availability zones within the region where this SKU is restricted.
type: list
sample: ["1", "2"]
'''


from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase
try:
from azure.mgmt.compute import ComputeManagementClient
from azure.core.exceptions import HttpResponseError
except ImportError:
# This is handled in azure_rm_common
pass


class AzureRMImageskuInfo(AzureRMModuleBase):
def __init__(self):

self.module_arg_spec = dict(
location=dict(type='str'),
publisher=dict(type='str'),
offer=dict(type='str'),
)

self.results = dict(
available_skus=[],
count=0
)
self.location = None
self.publisher = None
self.offer = None
super(AzureRMImageskuInfo, self).__init__(derived_arg_spec=self.module_arg_spec,
supports_check_mode=True,
supports_tags=False)

def exec_module(self, **kwargs):
for key in self.module_arg_spec:
setattr(self, key, kwargs[key])

available_skus = self.list_skus()
self.results['available_skus'] = available_skus
self.results['count'] = len(available_skus)
return self.results

def list_skus(self):
try:
compute_client = self.get_mgmt_svc_client(ComputeManagementClient,
base_url=self._cloud_environment.endpoints.resource_manager,
api_version='2021-07-01')
skus_result = compute_client.virtual_machine_images.list_skus(location=self.location,
publisher_name=self.publisher,
offer=self.offer)
available_skus = []

for sku_info in skus_result:
available_skus.append(sku_info.as_dict())
return available_skus

except HttpResponseError as e:
# Handle exceptions
raise e


def _match_location(loc, locations):
return next((x for x in locations if x.lower() == loc.lower()), None)


def _is_sku_available(sku_info, zone):
"""
The SKU is unavailable in the following cases:
1. regional restriction and the region is restricted
2. parameter "zone" is input which indicates only showing skus with availability zones.
Meanwhile, zonal restriction and all zones are restricted
"""
is_available = True
is_restrict_zone = False
is_restrict_location = False
if not sku_info.restrictions:
return is_available
for restriction in sku_info.restrictions:
if restriction.reason_code == 'NotAvailableForSubscription':
if restriction.type == 'Zone' and not (
set(sku_info.location_info[0].zones or []) - set(restriction.restriction_info.zones or [])):
is_restrict_zone = True
if restriction.type == 'Location' and (
sku_info.location_info[0].location in (restriction.restriction_info.locations or [])):
is_restrict_location = True
if is_restrict_location or (is_restrict_zone and zone):
is_available = False
break
return is_available


def main():
AzureRMImageskuInfo()


if __name__ == '__main__':
main()
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ all:
network: 10.42.8.0/24
subnet: 10.42.8.0/28

azure_test_image_skus:
network: 10.42.3.0/24
subnet: 10.42.3.0/28

vars:
ansible_connection: local
ansible_python_interpreter: "{{ ansible_playbook_python }}"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
- name: Set variables
ansible.builtin.include_tasks: setup.yml

- name: Set variables
ansible.builtin.set_fact:
network: 10.42.0.0/24
subnet: 10.42.0.0/28
vm_name: "vm{{ resource_group | hash('md5') | truncate(6, True, '') }}"
network_name: "vnet{{ resource_group | hash('md5') | truncate(6, True, '') }}"
subnet_name: "subnet{{ resource_group | hash('md5') | truncate(6, True, '') }}"
location: eastus
offer: 0001-com-ubuntu-server-focal
publisher: Canonical

- name: List available Image SKUs for 0001-com-ubuntu-server-focal
azure_rm_imagesku_info:
location: "{{ location }}"
offer: "{{ offer }}"
publisher: "{{ publisher }}"
register: available_image_skus_results

- name: Set specific 0001-com-ubuntu-server-focal image version
ansible.builtin.set_fact:
specific_image_name: "16.04.202104140"

- name: Get the first sku from the available skus list
ansible.builtin.set_fact:
first_image_sku_option: "{{ available_image_skus_results.available_skus[0] }}"

- name: SETUP | Create virtual network
azure_rm_virtualnetwork:
resource_group: "{{ resource_group }}"
name: "{{ network_name }}"
location: "{{ location }}"
address_prefixes: "{{ network }}"

- name: SETUP | Create subnet
azure_rm_subnet:
resource_group: "{{ resource_group }}"
name: "{{ subnet_name }}"
address_prefix: "{{ subnet }}"
virtual_network: "{{ network_name }}"

- name: Create VM with first Image SKU result
azure_rm_virtualmachine:
resource_group: "{{ resource_group }}"
name: "{{ vm_name }}"
admin_username: "testuser"
ssh_password_enabled: false
ssh_public_keys:
- path: /home/testuser/.ssh/authorized_keys
key_data: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDfoYlIV4lTPZTv7hXaVwQQuqBgGs4yeNRX0SPo2+HQt9u4X7IGwrtXc0nEUm6LfaCikMH58bOL8f20NTGz285kxdFHZRcBXtqmnMz2rXwhK9gwq5h1khc+GzHtdcJXsGA4y0xuaNcidcg04jxAlN/06fwb/VYwwWTVbypNC0gpGEpWckCNm8vlDlA55sU5et0SZ+J0RKVvEaweUOeNbFZqckGPA384imfeYlADppK/7eAxqfBVadVvZG8IJk4yvATgaIENIFj2cXxqu2mQ/Bp5Wr45uApvJsFXmi+v/nkiOEV1QpLOnEwAZo6EfFS4CCQtsymxJCl1PxdJ5LD4ZOtP [email protected]"
vm_size: Standard_B1ms
virtual_network: "{{ network_name }}"
image:
offer: "{{ offer }}"
publisher: "{{ publisher }}"
sku: "{{ first_image_sku_option.name }}"
version: "latest"
register: vm_output

- name: Ensure VM was created using the specific image sku
ansible.builtin.assert:
that:
- vm_output.ansible_facts.azure_vm.storage_profile.image_reference.sku == first_image_sku_option.name

- name: Delete VM
azure_rm_virtualmachine:
resource_group: "{{ resource_group }}"
name: "{{ vm_name }}"
remove_on_absent: all_autocreated
state: absent

- name: Destroy subnet
azure_rm_subnet:
resource_group: "{{ resource_group }}"
virtual_network: "{{ network_name }}"
name: "{{ subnet_name }}"
state: absent

- name: Destroy availability set
azure_rm_availabilityset:
resource_group: "{{ resource_group }}"
name: "{{ availability_set }}"
state: absent

- name: Destroy storage account
azure_rm_storageaccount:
resource_group: "{{ resource_group }}"
name: "{{ storage_account }}"
force_delete_nonempty: true
state: absent

- name: Destroy virtual network
azure_rm_virtualnetwork:
resource_group: "{{ resource_group }}"
name: "{{ network_name }}"
state: absent

0 comments on commit 4a8ca03

Please sign in to comment.