-
Notifications
You must be signed in to change notification settings - Fork 332
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ACA-1842: Image SKUs support in Ansible collection -
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
1 parent
1fd45ee
commit 4a8ca03
Showing
3 changed files
with
328 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
98 changes: 98 additions & 0 deletions
98
tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_image_skus.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |