shared image gallery modules (#57386)
* modules to handle shared image gallery * update test * and firewall update * fixed gallery problems * fixed gallery version * fix * several fixes to the gallery * several fixes * fixes * fix non-updatable * fixed test & image * fixed idempotency * fix test * image version test fixed * fixes * changed ux * trigger * fix syntax * fixed sanity * updated module + test delete * fixed some sanity & delete * continue fixing sanity * sanity fix and pause after deleting image version * extended delay * removed sanity ignore * try to ignore errors * repeat until successful * more retries * updated test, etc. * updated test * updated shared image gallery docs
This commit is contained in:
parent
eda5dd826f
commit
c9d82024c7
10 changed files with 1637 additions and 29 deletions
|
@ -140,34 +140,44 @@ class AzureRMModuleBaseExt(AzureRMModuleBase):
|
|||
if new is None:
|
||||
return True
|
||||
elif isinstance(new, dict):
|
||||
comparison_result = True
|
||||
if not isinstance(old, dict):
|
||||
result['compare'] = 'changed [' + path + '] old dict is null'
|
||||
return False
|
||||
for k in new.keys():
|
||||
if not self.default_compare(modifiers, new.get(k), old.get(k, None), path + '/' + k, result):
|
||||
return False
|
||||
return True
|
||||
elif isinstance(new, list):
|
||||
if not isinstance(old, list) or len(new) != len(old):
|
||||
result['compare'] = 'changed [' + path + '] length is different or null'
|
||||
return False
|
||||
if isinstance(old[0], dict):
|
||||
key = None
|
||||
if 'id' in old[0] and 'id' in new[0]:
|
||||
key = 'id'
|
||||
elif 'name' in old[0] and 'name' in new[0]:
|
||||
key = 'name'
|
||||
else:
|
||||
key = next(iter(old[0]))
|
||||
new = sorted(new, key=lambda x: x.get(key, None))
|
||||
old = sorted(old, key=lambda x: x.get(key, None))
|
||||
result['compare'].append('changed [' + path + '] old dict is null')
|
||||
comparison_result = False
|
||||
else:
|
||||
new = sorted(new)
|
||||
old = sorted(old)
|
||||
for i in range(len(new)):
|
||||
if not self.default_compare(modifiers, new[i], old[i], path + '/*', result):
|
||||
return False
|
||||
return True
|
||||
for k in set(new.keys()) | set(old.keys()):
|
||||
new_item = new.get(k, None)
|
||||
old_item = old.get(k, None)
|
||||
if new_item is None:
|
||||
if isinstance(old_item, dict):
|
||||
new[k] = old_item
|
||||
result['compare'].append('new item was empty, using old [' + path + '][ ' + k + ' ]')
|
||||
elif not self.default_compare(modifiers, new_item, old_item, path + '/' + k, result):
|
||||
comparison_result = False
|
||||
return comparison_result
|
||||
elif isinstance(new, list):
|
||||
comparison_result = True
|
||||
if not isinstance(old, list) or len(new) != len(old):
|
||||
result['compare'].append('changed [' + path + '] length is different or old value is null')
|
||||
comparison_result = False
|
||||
else:
|
||||
if isinstance(old[0], dict):
|
||||
key = None
|
||||
if 'id' in old[0] and 'id' in new[0]:
|
||||
key = 'id'
|
||||
elif 'name' in old[0] and 'name' in new[0]:
|
||||
key = 'name'
|
||||
else:
|
||||
key = next(iter(old[0]))
|
||||
new = sorted(new, key=lambda x: x.get(key, None))
|
||||
old = sorted(old, key=lambda x: x.get(key, None))
|
||||
else:
|
||||
new = sorted(new)
|
||||
old = sorted(old)
|
||||
for i in range(len(new)):
|
||||
if not self.default_compare(modifiers, new[i], old[i], path + '/*', result):
|
||||
comparison_result = False
|
||||
return comparison_result
|
||||
else:
|
||||
updatable = modifiers.get(path, {}).get('updatable', True)
|
||||
comparison = modifiers.get(path, {}).get('comparison', 'default')
|
||||
|
@ -182,7 +192,7 @@ class AzureRMModuleBaseExt(AzureRMModuleBase):
|
|||
new = new.replace(' ', '').lower()
|
||||
old = old.replace(' ', '').lower()
|
||||
if str(new) != str(old):
|
||||
result['compare'] = 'changed [' + path + '] ' + str(new) + ' != ' + str(old) + ' - ' + str(comparison)
|
||||
result['compare'].append('changed [' + path + '] ' + str(new) + ' != ' + str(old) + ' - ' + str(comparison))
|
||||
if updatable:
|
||||
return False
|
||||
else:
|
||||
|
|
|
@ -19,7 +19,7 @@ module: azure_rm_azurefirewall
|
|||
version_added: '2.9'
|
||||
short_description: Manage Azure Firewall instance.
|
||||
description:
|
||||
- 'Create, update and delete instance of Azure Firewall.'
|
||||
- Create, update and delete instance of Azure Firewall.
|
||||
options:
|
||||
resource_group:
|
||||
description:
|
||||
|
@ -600,6 +600,7 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt):
|
|||
modifiers = {}
|
||||
self.create_compare_modifiers(self.module_arg_spec, '', modifiers)
|
||||
self.results['modifiers'] = modifiers
|
||||
self.results['compare'] = []
|
||||
if not self.default_compare(modifiers, self.body, old_response, '', self.results):
|
||||
self.to_do = Actions.Update
|
||||
|
||||
|
|
314
lib/ansible/modules/cloud/azure/azure_rm_gallery.py
Normal file
314
lib/ansible/modules/cloud/azure/azure_rm_gallery.py
Normal file
|
@ -0,0 +1,314 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright (c) 2019 Zim Kalinowski, (@zikalino)
|
||||
#
|
||||
# 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
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: azure_rm_gallery
|
||||
version_added: '2.9'
|
||||
short_description: Manage Azure Shared Image Gallery instance.
|
||||
description:
|
||||
- 'Create, update and delete instance of Azure Shared Image Gallery (SIG).'
|
||||
options:
|
||||
resource_group:
|
||||
description:
|
||||
- The name of the resource group.
|
||||
required: true
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- >-
|
||||
The name of the Shared Image Gallery.
|
||||
Valid names consist of less than 80 alphanumeric characters, underscores and periods.
|
||||
required: true
|
||||
type: str
|
||||
location:
|
||||
description:
|
||||
- Resource location
|
||||
type: str
|
||||
description:
|
||||
description:
|
||||
- >-
|
||||
The description of this Shared Image Gallery resource. This property is
|
||||
updatable.
|
||||
type: str
|
||||
state:
|
||||
description:
|
||||
- Assert the state of the Gallery.
|
||||
- >-
|
||||
Use C(present) to create or update an Gallery and C(absent) to delete
|
||||
it.
|
||||
default: present
|
||||
type: str
|
||||
choices:
|
||||
- absent
|
||||
- present
|
||||
extends_documentation_fragment:
|
||||
- azure
|
||||
- azure_tags
|
||||
author:
|
||||
- Zim Kalinowski (@zikalino)
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Create or update a simple gallery.
|
||||
azure_rm_gallery:
|
||||
resource_group: myResourceGroup
|
||||
name: myGallery1283
|
||||
location: West US
|
||||
description: This is the gallery description.
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
id:
|
||||
description:
|
||||
- Resource Id
|
||||
returned: always
|
||||
type: str
|
||||
sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Compute/galleries/myGallery1283"
|
||||
'''
|
||||
|
||||
import time
|
||||
import json
|
||||
import re
|
||||
from ansible.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt
|
||||
from ansible.module_utils.azure_rm_common_rest import GenericRestClient
|
||||
from copy import deepcopy
|
||||
try:
|
||||
from msrestazure.azure_exceptions import CloudError
|
||||
except ImportError:
|
||||
# This is handled in azure_rm_common
|
||||
pass
|
||||
|
||||
|
||||
class Actions:
|
||||
NoAction, Create, Update, Delete = range(4)
|
||||
|
||||
|
||||
class AzureRMGalleries(AzureRMModuleBaseExt):
|
||||
def __init__(self):
|
||||
self.module_arg_spec = dict(
|
||||
resource_group=dict(
|
||||
type='str',
|
||||
updatable=False,
|
||||
disposition='resourceGroupName',
|
||||
required=True
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
updatable=False,
|
||||
disposition='galleryName',
|
||||
required=True
|
||||
),
|
||||
location=dict(
|
||||
type='str',
|
||||
updatable=False,
|
||||
disposition='/'
|
||||
),
|
||||
description=dict(
|
||||
type='str',
|
||||
disposition='/properties/*'
|
||||
),
|
||||
state=dict(
|
||||
type='str',
|
||||
default='present',
|
||||
choices=['present', 'absent']
|
||||
)
|
||||
)
|
||||
|
||||
self.resource_group = None
|
||||
self.name = None
|
||||
self.gallery = None
|
||||
|
||||
self.results = dict(changed=False)
|
||||
self.mgmt_client = None
|
||||
self.state = None
|
||||
self.url = None
|
||||
self.status_code = [200, 201, 202]
|
||||
self.to_do = Actions.NoAction
|
||||
|
||||
self.body = {}
|
||||
self.query_parameters = {}
|
||||
self.query_parameters['api-version'] = '2019-03-01'
|
||||
self.header_parameters = {}
|
||||
self.header_parameters['Content-Type'] = 'application/json; charset=utf-8'
|
||||
|
||||
super(AzureRMGalleries, self).__init__(derived_arg_spec=self.module_arg_spec,
|
||||
supports_check_mode=True,
|
||||
supports_tags=True)
|
||||
|
||||
def exec_module(self, **kwargs):
|
||||
for key in list(self.module_arg_spec.keys()):
|
||||
if hasattr(self, key):
|
||||
setattr(self, key, kwargs[key])
|
||||
elif kwargs[key] is not None:
|
||||
self.body[key] = kwargs[key]
|
||||
|
||||
self.inflate_parameters(self.module_arg_spec, self.body, 0)
|
||||
|
||||
old_response = None
|
||||
response = None
|
||||
|
||||
self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient,
|
||||
base_url=self._cloud_environment.endpoints.resource_manager)
|
||||
|
||||
resource_group = self.get_resource_group(self.resource_group)
|
||||
|
||||
if 'location' not in self.body:
|
||||
self.body['location'] = resource_group.location
|
||||
|
||||
self.url = ('/subscriptions' +
|
||||
'/{{ subscription_id }}' +
|
||||
'/resourceGroups' +
|
||||
'/{{ resource_group }}' +
|
||||
'/providers' +
|
||||
'/Microsoft.Compute' +
|
||||
'/galleries' +
|
||||
'/{{ gallery_name }}')
|
||||
self.url = self.url.replace('{{ subscription_id }}', self.subscription_id)
|
||||
self.url = self.url.replace('{{ resource_group }}', self.resource_group)
|
||||
self.url = self.url.replace('{{ gallery_name }}', self.name)
|
||||
|
||||
old_response = self.get_resource()
|
||||
|
||||
if not old_response:
|
||||
self.log("Gallery instance doesn't exist")
|
||||
|
||||
if self.state == 'absent':
|
||||
self.log("Old instance didn't exist")
|
||||
else:
|
||||
self.to_do = Actions.Create
|
||||
else:
|
||||
self.log('Gallery instance already exists')
|
||||
|
||||
if self.state == 'absent':
|
||||
self.to_do = Actions.Delete
|
||||
else:
|
||||
modifiers = {}
|
||||
self.create_compare_modifiers(self.module_arg_spec, '', modifiers)
|
||||
self.results['modifiers'] = modifiers
|
||||
self.results['compare'] = []
|
||||
if not self.default_compare(modifiers, self.body, old_response, '', self.results):
|
||||
self.to_do = Actions.Update
|
||||
self.body['properties'].pop('identifier', None)
|
||||
|
||||
if (self.to_do == Actions.Create) or (self.to_do == Actions.Update):
|
||||
self.log('Need to Create / Update the Gallery instance')
|
||||
|
||||
if self.check_mode:
|
||||
self.results['changed'] = True
|
||||
return self.results
|
||||
|
||||
response = self.create_update_resource()
|
||||
|
||||
# if not old_response:
|
||||
self.results['changed'] = True
|
||||
# else:
|
||||
# self.results['changed'] = old_response.__ne__(response)
|
||||
self.log('Creation / Update done')
|
||||
elif self.to_do == Actions.Delete:
|
||||
self.log('Gallery instance deleted')
|
||||
self.results['changed'] = True
|
||||
|
||||
if self.check_mode:
|
||||
return self.results
|
||||
|
||||
self.delete_resource()
|
||||
|
||||
# make sure instance is actually deleted, for some Azure resources, instance is hanging around
|
||||
# for some time after deletion -- this should be really fixed in Azure
|
||||
while self.get_resource():
|
||||
time.sleep(20)
|
||||
else:
|
||||
self.log('Gallery instance unchanged')
|
||||
self.results['changed'] = False
|
||||
response = old_response
|
||||
|
||||
if response:
|
||||
self.results["id"] = response["id"]
|
||||
|
||||
return self.results
|
||||
|
||||
def create_update_resource(self):
|
||||
# self.log('Creating / Updating the Gallery instance {0}'.format(self.))
|
||||
|
||||
try:
|
||||
response = self.mgmt_client.query(self.url,
|
||||
'PUT',
|
||||
self.query_parameters,
|
||||
self.header_parameters,
|
||||
self.body,
|
||||
self.status_code,
|
||||
600,
|
||||
30)
|
||||
except CloudError as exc:
|
||||
self.log('Error attempting to create the Gallery instance.')
|
||||
self.fail('Error creating the Gallery instance: {0}'.format(str(exc)))
|
||||
|
||||
try:
|
||||
response = json.loads(response.text)
|
||||
except Exception:
|
||||
response = {'text': response.text}
|
||||
pass
|
||||
|
||||
return response
|
||||
|
||||
def delete_resource(self):
|
||||
# self.log('Deleting the Gallery instance {0}'.format(self.))
|
||||
try:
|
||||
response = self.mgmt_client.query(self.url,
|
||||
'DELETE',
|
||||
self.query_parameters,
|
||||
self.header_parameters,
|
||||
None,
|
||||
self.status_code,
|
||||
600,
|
||||
30)
|
||||
except CloudError as e:
|
||||
self.log('Error attempting to delete the Gallery instance.')
|
||||
self.fail('Error deleting the Gallery instance: {0}'.format(str(e)))
|
||||
|
||||
return True
|
||||
|
||||
def get_resource(self):
|
||||
# self.log('Checking if the Gallery instance {0} is present'.format(self.))
|
||||
found = False
|
||||
try:
|
||||
response = self.mgmt_client.query(self.url,
|
||||
'GET',
|
||||
self.query_parameters,
|
||||
self.header_parameters,
|
||||
None,
|
||||
self.status_code,
|
||||
600,
|
||||
30)
|
||||
response = json.loads(response.text)
|
||||
found = True
|
||||
self.log("Response : {0}".format(response))
|
||||
# self.log("AzureFirewall instance : {0} found".format(response.name))
|
||||
except CloudError as e:
|
||||
self.log('Did not find the AzureFirewall instance.')
|
||||
if found is True:
|
||||
return response
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
AzureRMGalleries()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
554
lib/ansible/modules/cloud/azure/azure_rm_galleryimage.py
Normal file
554
lib/ansible/modules/cloud/azure/azure_rm_galleryimage.py
Normal file
|
@ -0,0 +1,554 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright (c) 2019 Zim Kalinowski, (@zikalino)
|
||||
#
|
||||
# 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
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: azure_rm_galleryimage
|
||||
version_added: '2.9'
|
||||
short_description: Manage Azure SIG Image instance.
|
||||
description:
|
||||
- 'Create, update and delete instance of Azure SIG Image.'
|
||||
options:
|
||||
resource_group:
|
||||
description:
|
||||
- The name of the resource group.
|
||||
required: true
|
||||
type: str
|
||||
gallery_name:
|
||||
description:
|
||||
- >-
|
||||
The name of the Shared Image Gallery in which the Image Definition is to
|
||||
be created.
|
||||
required: true
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- >-
|
||||
The name of the gallery Image Definition to be created or updated. The
|
||||
allowed characters are alphabets and numbers with dots, dashes, and
|
||||
periods allowed in the middle. The maximum length is 80 characters.
|
||||
required: true
|
||||
type: str
|
||||
location:
|
||||
description:
|
||||
- Resource location
|
||||
type: str
|
||||
description:
|
||||
description:
|
||||
- >-
|
||||
The description of this gallery Image Definition resource. This property
|
||||
is updatable.
|
||||
type: str
|
||||
eula:
|
||||
description:
|
||||
- The Eula agreement for the gallery Image Definition.
|
||||
type: str
|
||||
privacy_statement_uri:
|
||||
description:
|
||||
- The privacy statement uri.
|
||||
type: str
|
||||
release_note_uri:
|
||||
description:
|
||||
- The release note uri.
|
||||
type: str
|
||||
os_type:
|
||||
description:
|
||||
- >-
|
||||
This property allows you to specify the type of the OS that is included
|
||||
in the disk when creating a VM from a managed image.
|
||||
choices:
|
||||
- windows
|
||||
- linux
|
||||
required: true
|
||||
type: str
|
||||
os_state:
|
||||
description:
|
||||
- The allowed values for OS State are 'Generalized'.
|
||||
choices:
|
||||
- generalized
|
||||
- specialized
|
||||
required: true
|
||||
type: str
|
||||
end_of_life_date:
|
||||
description:
|
||||
- >-
|
||||
The end of life date of the gallery Image Definition. This property can
|
||||
be used for decommissioning purposes. This property is updatable.
|
||||
Format should be according to ISO-8601, for instance "2019-06-26".
|
||||
type: str
|
||||
identifier:
|
||||
description:
|
||||
- Image identifier.
|
||||
required: true
|
||||
type: dict
|
||||
suboptions:
|
||||
publisher:
|
||||
description:
|
||||
- The name of the gallery Image Definition publisher.
|
||||
required: true
|
||||
type: str
|
||||
offer:
|
||||
description:
|
||||
- The name of the gallery Image Definition offer.
|
||||
required: true
|
||||
type: str
|
||||
sku:
|
||||
description:
|
||||
- The name of the gallery Image Definition SKU.
|
||||
required: true
|
||||
type: str
|
||||
recommended:
|
||||
description:
|
||||
- Recommended parameter values.
|
||||
type: dict
|
||||
suboptions:
|
||||
v_cpus:
|
||||
description:
|
||||
- Number of virtual CPUs.
|
||||
type: dict
|
||||
suboptions:
|
||||
min:
|
||||
description:
|
||||
- The minimum number of the resource.
|
||||
type: int
|
||||
max:
|
||||
description:
|
||||
- The maximum number of the resource.
|
||||
type: int
|
||||
memory:
|
||||
description:
|
||||
- Memory.
|
||||
type: dict
|
||||
suboptions:
|
||||
min:
|
||||
description:
|
||||
- The minimum number of the resource.
|
||||
type: int
|
||||
max:
|
||||
description:
|
||||
- The maximum number of the resource.
|
||||
type: int
|
||||
disallowed:
|
||||
description:
|
||||
- Disalloved parameter values.
|
||||
type: dict
|
||||
suboptions:
|
||||
disk_types:
|
||||
description:
|
||||
- A list of disallowed disk types.
|
||||
type: list
|
||||
purchase_plan:
|
||||
description:
|
||||
- Purchase plan.
|
||||
type: dict
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- The plan ID.
|
||||
type: str
|
||||
publisher:
|
||||
description:
|
||||
- The publisher ID.
|
||||
type: str
|
||||
product:
|
||||
description:
|
||||
- The product ID.
|
||||
type: str
|
||||
state:
|
||||
description:
|
||||
- Assert the state of the GalleryImage.
|
||||
- >-
|
||||
Use C(present) to create or update an GalleryImage and C(absent) to
|
||||
delete it.
|
||||
default: present
|
||||
choices:
|
||||
- absent
|
||||
- present
|
||||
type: str
|
||||
extends_documentation_fragment:
|
||||
- azure
|
||||
- azure_tags
|
||||
author:
|
||||
- Zim Kalinowski (@zikalino)
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Create or update gallery image
|
||||
azure_rm_galleryimage:
|
||||
resource_group: myResourceGroup
|
||||
gallery_name: myGallery1283
|
||||
name: myImage
|
||||
location: West US
|
||||
os_type: linux
|
||||
os_state: generalized
|
||||
identifier:
|
||||
publisher: myPublisherName
|
||||
offer: myOfferName
|
||||
sku: mySkuName
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
id:
|
||||
description:
|
||||
- Resource Id
|
||||
returned: always
|
||||
type: str
|
||||
sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Compute/galleries/myGalle
|
||||
ry1283/images/myImage"
|
||||
'''
|
||||
|
||||
import time
|
||||
import json
|
||||
import re
|
||||
from ansible.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt
|
||||
from ansible.module_utils.azure_rm_common_rest import GenericRestClient
|
||||
from copy import deepcopy
|
||||
try:
|
||||
from msrestazure.azure_exceptions import CloudError
|
||||
except ImportError:
|
||||
# This is handled in azure_rm_common
|
||||
pass
|
||||
|
||||
|
||||
class Actions:
|
||||
NoAction, Create, Update, Delete = range(4)
|
||||
|
||||
|
||||
class AzureRMGalleryImages(AzureRMModuleBaseExt):
|
||||
def __init__(self):
|
||||
self.module_arg_spec = dict(
|
||||
resource_group=dict(
|
||||
type='str',
|
||||
updatable=False,
|
||||
disposition='resourceGroupName',
|
||||
required=True
|
||||
),
|
||||
gallery_name=dict(
|
||||
type='str',
|
||||
updatable=False,
|
||||
disposition='galleryName',
|
||||
required=True
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
updatable=False,
|
||||
disposition='galleryImageName',
|
||||
required=True
|
||||
),
|
||||
location=dict(
|
||||
type='str',
|
||||
updatable=False,
|
||||
disposition='/'
|
||||
),
|
||||
description=dict(
|
||||
type='str',
|
||||
disposition='/properties/*'
|
||||
),
|
||||
eula=dict(
|
||||
type='str',
|
||||
disposition='/properties/*'
|
||||
),
|
||||
privacy_statement_uri=dict(
|
||||
type='str',
|
||||
disposition='/properties/privacyStatementUri'
|
||||
),
|
||||
release_note_uri=dict(
|
||||
type='str',
|
||||
disposition='/properties/releaseNoteUri'
|
||||
),
|
||||
os_type=dict(
|
||||
type='str',
|
||||
disposition='/properties/osType',
|
||||
choices=['windows',
|
||||
'linux']
|
||||
),
|
||||
os_state=dict(
|
||||
type='str',
|
||||
disposition='/properties/osState',
|
||||
choices=['generalized',
|
||||
'specialized']
|
||||
),
|
||||
end_of_life_date=dict(
|
||||
type='str',
|
||||
disposition='/properties/endOfLifeDate'
|
||||
),
|
||||
identifier=dict(
|
||||
type='dict',
|
||||
disposition='/properties/*',
|
||||
options=dict(
|
||||
publisher=dict(
|
||||
type='str',
|
||||
required=True,
|
||||
updatable=False
|
||||
),
|
||||
offer=dict(
|
||||
type='str',
|
||||
required=True
|
||||
),
|
||||
sku=dict(
|
||||
type='str',
|
||||
required=True
|
||||
)
|
||||
)
|
||||
),
|
||||
recommended=dict(
|
||||
type='dict',
|
||||
disposition='/properties/*',
|
||||
options=dict(
|
||||
v_cpus=dict(
|
||||
type='dict',
|
||||
disposition='vCPUs',
|
||||
options=dict(
|
||||
min=dict(
|
||||
type='int'
|
||||
),
|
||||
max=dict(
|
||||
type='int'
|
||||
)
|
||||
)
|
||||
),
|
||||
memory=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
min=dict(
|
||||
type='int'
|
||||
),
|
||||
max=dict(
|
||||
type='int'
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
disallowed=dict(
|
||||
type='dict',
|
||||
disposition='/properties/*',
|
||||
options=dict(
|
||||
disk_types=dict(
|
||||
type='list',
|
||||
disposition='diskTypes'
|
||||
)
|
||||
)
|
||||
),
|
||||
purchase_plan=dict(
|
||||
type='dict',
|
||||
disposition='/properties/purchasePlan',
|
||||
options=dict(
|
||||
name=dict(
|
||||
type='str'
|
||||
),
|
||||
publisher=dict(
|
||||
type='str'
|
||||
),
|
||||
product=dict(
|
||||
type='str'
|
||||
)
|
||||
)
|
||||
),
|
||||
state=dict(
|
||||
type='str',
|
||||
default='present',
|
||||
choices=['present', 'absent']
|
||||
)
|
||||
)
|
||||
|
||||
self.resource_group = None
|
||||
self.gallery_name = None
|
||||
self.name = None
|
||||
self.gallery_image = None
|
||||
|
||||
self.results = dict(changed=False)
|
||||
self.mgmt_client = None
|
||||
self.state = None
|
||||
self.url = None
|
||||
self.status_code = [200, 201, 202]
|
||||
self.to_do = Actions.NoAction
|
||||
|
||||
self.body = {}
|
||||
self.query_parameters = {}
|
||||
self.query_parameters['api-version'] = '2019-03-01'
|
||||
self.header_parameters = {}
|
||||
self.header_parameters['Content-Type'] = 'application/json; charset=utf-8'
|
||||
|
||||
super(AzureRMGalleryImages, self).__init__(derived_arg_spec=self.module_arg_spec,
|
||||
supports_check_mode=True,
|
||||
supports_tags=True)
|
||||
|
||||
def exec_module(self, **kwargs):
|
||||
for key in list(self.module_arg_spec.keys()):
|
||||
if hasattr(self, key):
|
||||
setattr(self, key, kwargs[key])
|
||||
elif kwargs[key] is not None:
|
||||
self.body[key] = kwargs[key]
|
||||
|
||||
self.inflate_parameters(self.module_arg_spec, self.body, 0)
|
||||
|
||||
old_response = None
|
||||
response = None
|
||||
|
||||
self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient,
|
||||
base_url=self._cloud_environment.endpoints.resource_manager)
|
||||
|
||||
resource_group = self.get_resource_group(self.resource_group)
|
||||
|
||||
if 'location' not in self.body:
|
||||
self.body['location'] = resource_group.location
|
||||
|
||||
self.url = ('/subscriptions' +
|
||||
'/{{ subscription_id }}' +
|
||||
'/resourceGroups' +
|
||||
'/{{ resource_group }}' +
|
||||
'/providers' +
|
||||
'/Microsoft.Compute' +
|
||||
'/galleries' +
|
||||
'/{{ gallery_name }}' +
|
||||
'/images' +
|
||||
'/{{ image_name }}')
|
||||
self.url = self.url.replace('{{ subscription_id }}', self.subscription_id)
|
||||
self.url = self.url.replace('{{ resource_group }}', self.resource_group)
|
||||
self.url = self.url.replace('{{ gallery_name }}', self.gallery_name)
|
||||
self.url = self.url.replace('{{ image_name }}', self.name)
|
||||
|
||||
old_response = self.get_resource()
|
||||
|
||||
if not old_response:
|
||||
self.log("GalleryImage instance doesn't exist")
|
||||
|
||||
if self.state == 'absent':
|
||||
self.log("Old instance didn't exist")
|
||||
else:
|
||||
self.to_do = Actions.Create
|
||||
else:
|
||||
self.log('GalleryImage instance already exists')
|
||||
|
||||
if self.state == 'absent':
|
||||
self.to_do = Actions.Delete
|
||||
else:
|
||||
modifiers = {}
|
||||
self.create_compare_modifiers(self.module_arg_spec, '', modifiers)
|
||||
self.results['modifiers'] = modifiers
|
||||
self.results['compare'] = []
|
||||
if not self.default_compare(modifiers, self.body, old_response, '', self.results):
|
||||
self.to_do = Actions.Update
|
||||
|
||||
if (self.to_do == Actions.Create) or (self.to_do == Actions.Update):
|
||||
self.log('Need to Create / Update the GalleryImage instance')
|
||||
|
||||
if self.check_mode:
|
||||
self.results['changed'] = True
|
||||
return self.results
|
||||
|
||||
response = self.create_update_resource()
|
||||
|
||||
# if not old_response:
|
||||
self.results['changed'] = True
|
||||
# else:
|
||||
# self.results['changed'] = old_response.__ne__(response)
|
||||
self.log('Creation / Update done')
|
||||
elif self.to_do == Actions.Delete:
|
||||
self.log('GalleryImage instance deleted')
|
||||
self.results['changed'] = True
|
||||
|
||||
if self.check_mode:
|
||||
return self.results
|
||||
|
||||
self.delete_resource()
|
||||
|
||||
# make sure instance is actually deleted, for some Azure resources, instance is hanging around
|
||||
# for some time after deletion -- this should be really fixed in Azure
|
||||
while self.get_resource():
|
||||
time.sleep(20)
|
||||
else:
|
||||
self.log('GalleryImage instance unchanged')
|
||||
self.results['changed'] = False
|
||||
response = old_response
|
||||
|
||||
if response:
|
||||
self.results["id"] = response["id"]
|
||||
|
||||
return self.results
|
||||
|
||||
def create_update_resource(self):
|
||||
# self.log('Creating / Updating the GalleryImage instance {0}'.format(self.))
|
||||
|
||||
try:
|
||||
response = self.mgmt_client.query(self.url,
|
||||
'PUT',
|
||||
self.query_parameters,
|
||||
self.header_parameters,
|
||||
self.body,
|
||||
self.status_code,
|
||||
600,
|
||||
30)
|
||||
except CloudError as exc:
|
||||
self.log('Error attempting to create the GalleryImage instance.')
|
||||
self.fail('Error creating the GalleryImage instance: {0}'.format(str(exc)))
|
||||
|
||||
try:
|
||||
response = json.loads(response.text)
|
||||
except Exception:
|
||||
response = {'text': response.text}
|
||||
pass
|
||||
|
||||
return response
|
||||
|
||||
def delete_resource(self):
|
||||
# self.log('Deleting the GalleryImage instance {0}'.format(self.))
|
||||
try:
|
||||
response = self.mgmt_client.query(self.url,
|
||||
'DELETE',
|
||||
self.query_parameters,
|
||||
self.header_parameters,
|
||||
None,
|
||||
self.status_code,
|
||||
600,
|
||||
30)
|
||||
except CloudError as e:
|
||||
self.log('Error attempting to delete the GalleryImage instance.')
|
||||
self.fail('Error deleting the GalleryImage instance: {0}'.format(str(e)))
|
||||
|
||||
return True
|
||||
|
||||
def get_resource(self):
|
||||
# self.log('Checking if the GalleryImage instance {0} is present'.format(self.))
|
||||
found = False
|
||||
try:
|
||||
response = self.mgmt_client.query(self.url,
|
||||
'GET',
|
||||
self.query_parameters,
|
||||
self.header_parameters,
|
||||
None,
|
||||
self.status_code,
|
||||
600,
|
||||
30)
|
||||
response = json.loads(response.text)
|
||||
found = True
|
||||
self.log("Response : {0}".format(response))
|
||||
# self.log("AzureFirewall instance : {0} found".format(response.name))
|
||||
except CloudError as e:
|
||||
self.log('Did not find the AzureFirewall instance.')
|
||||
if found is True:
|
||||
return response
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
AzureRMGalleryImages()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
459
lib/ansible/modules/cloud/azure/azure_rm_galleryimageversion.py
Normal file
459
lib/ansible/modules/cloud/azure/azure_rm_galleryimageversion.py
Normal file
|
@ -0,0 +1,459 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright (c) 2019 Zim Kalinowski, (@zikalino)
|
||||
#
|
||||
# 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
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: azure_rm_galleryimageversion
|
||||
version_added: '2.9'
|
||||
short_description: Manage Azure SIG Image Version instance.
|
||||
description:
|
||||
- 'Create, update and delete instance of Azure SIG Image Version.'
|
||||
options:
|
||||
resource_group:
|
||||
description:
|
||||
- The name of the resource group.
|
||||
required: true
|
||||
type: str
|
||||
gallery_name:
|
||||
description:
|
||||
- >-
|
||||
The name of the Shared Image Gallery in which the Image Definition
|
||||
resides.
|
||||
required: true
|
||||
type: str
|
||||
gallery_image_name:
|
||||
description:
|
||||
- >-
|
||||
The name of the gallery Image Definition in which the Image Version is
|
||||
to be created.
|
||||
required: true
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- >-
|
||||
The name of the gallery Image Version to be created. Needs to follow
|
||||
semantic version name pattern: The allowed characters are digit and
|
||||
period. Digits must be within the range of a 32-bit integer. Format:
|
||||
<MajorVersion>.<MinorVersion>.<Patch>
|
||||
required: true
|
||||
type: str
|
||||
location:
|
||||
description:
|
||||
- Resource location
|
||||
type: str
|
||||
publishing_profile:
|
||||
description:
|
||||
- Publishing profile.
|
||||
required: true
|
||||
type: dict
|
||||
suboptions:
|
||||
target_regions:
|
||||
description:
|
||||
- >-
|
||||
The target regions where the Image Version is going to be replicated
|
||||
to. This property is updatable.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Region name.
|
||||
type: str
|
||||
regional_replica_count:
|
||||
description:
|
||||
- >-
|
||||
The number of replicas of the Image Version to be created per
|
||||
region. This property would take effect for a region when
|
||||
regionalReplicaCount is not specified. This property is updatable.
|
||||
type: str
|
||||
storage_account_type:
|
||||
description:
|
||||
- Storage account type.
|
||||
type: str
|
||||
managed_image:
|
||||
description:
|
||||
- Managed image reference, could be resource id, or dictionary containing C(resource_group) and C(name)
|
||||
required: true
|
||||
type: raw
|
||||
replica_count:
|
||||
description:
|
||||
- >-
|
||||
The number of replicas of the Image Version to be created per
|
||||
region. This property would take effect for a region when
|
||||
regionalReplicaCount is not specified. This property is updatable.
|
||||
type: number
|
||||
exclude_from_latest:
|
||||
description:
|
||||
- >-
|
||||
If set to true, Virtual Machines deployed from the latest version of
|
||||
the Image Definition won't use this Image Version.
|
||||
type: bool
|
||||
end_of_life_date:
|
||||
description:
|
||||
- >-
|
||||
The end of life date of the gallery Image Version. This property can
|
||||
be used for decommissioning purposes. This property is updatable.
|
||||
Format should be according to ISO-8601, for instance "2019-06-26".
|
||||
type: str
|
||||
storage_account_type:
|
||||
description:
|
||||
- >-
|
||||
Specifies the storage account type to be used to store the image.
|
||||
This property is not updatable.
|
||||
type: str
|
||||
state:
|
||||
description:
|
||||
- Assert the state of the GalleryImageVersion.
|
||||
- >-
|
||||
Use C(present) to create or update an GalleryImageVersion and C(absent)
|
||||
to delete it.
|
||||
default: present
|
||||
choices:
|
||||
- absent
|
||||
- present
|
||||
type: str
|
||||
extends_documentation_fragment:
|
||||
- azure
|
||||
- azure_tags
|
||||
author:
|
||||
- Zim Kalinowski (@zikalino)
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Create or update a simple gallery Image Version.
|
||||
azure_rm_galleryimageversion:
|
||||
resource_group: myResourceGroup
|
||||
gallery_name: myGallery1283
|
||||
gallery_image_name: myImage
|
||||
name: 10.1.3
|
||||
location: West US
|
||||
publishing_profile:
|
||||
end_of_life_date: "2020-10-01t00:00:00+00:00"
|
||||
exclude_from_latest: yes
|
||||
replica_count: 3
|
||||
storage_account_type: Standard_LRS
|
||||
target_regions:
|
||||
- name: West US
|
||||
regional_replica_count: 1
|
||||
- name: East US
|
||||
regional_replica_count: 2
|
||||
storage_account_type: Standard_ZRS
|
||||
managed_image:
|
||||
name: myImage
|
||||
resource_group: myResourceGroup
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
id:
|
||||
description:
|
||||
- Resource Id
|
||||
returned: always
|
||||
type: str
|
||||
sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Compute/galleries/myGalle
|
||||
ry1283/images/myImage/versions/10.1.3"
|
||||
'''
|
||||
|
||||
import time
|
||||
import json
|
||||
import re
|
||||
from ansible.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt
|
||||
from ansible.module_utils.azure_rm_common_rest import GenericRestClient
|
||||
from copy import deepcopy
|
||||
try:
|
||||
from msrestazure.azure_exceptions import CloudError
|
||||
except ImportError:
|
||||
# This is handled in azure_rm_common
|
||||
pass
|
||||
|
||||
|
||||
class Actions:
|
||||
NoAction, Create, Update, Delete = range(4)
|
||||
|
||||
|
||||
class AzureRMGalleryImageVersions(AzureRMModuleBaseExt):
|
||||
def __init__(self):
|
||||
self.module_arg_spec = dict(
|
||||
resource_group=dict(
|
||||
type='str',
|
||||
updatable=False,
|
||||
disposition='resourceGroupName',
|
||||
required=True
|
||||
),
|
||||
gallery_name=dict(
|
||||
type='str',
|
||||
updatable=False,
|
||||
disposition='galleryName',
|
||||
required=True
|
||||
),
|
||||
gallery_image_name=dict(
|
||||
type='str',
|
||||
updatable=False,
|
||||
disposition='galleryImageName',
|
||||
required=True
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
updatable=False,
|
||||
disposition='galleryImageVersionName',
|
||||
required=True
|
||||
),
|
||||
location=dict(
|
||||
type='str',
|
||||
updatable=False,
|
||||
disposition='/'
|
||||
),
|
||||
publishing_profile=dict(
|
||||
type='dict',
|
||||
disposition='/properties/publishingProfile',
|
||||
options=dict(
|
||||
target_regions=dict(
|
||||
type='list',
|
||||
disposition='targetRegions',
|
||||
options=dict(
|
||||
name=dict(
|
||||
type='str',
|
||||
required=True
|
||||
),
|
||||
regional_replica_count=dict(
|
||||
type='int',
|
||||
disposition='regionalReplicaCount'
|
||||
),
|
||||
storage_account_type=dict(
|
||||
type='str',
|
||||
disposition='storageAccountType'
|
||||
)
|
||||
)
|
||||
),
|
||||
managed_image=dict(
|
||||
type='raw',
|
||||
pattern=('/subscriptions/{subscription_id}/resourceGroups'
|
||||
'/{resource_group}/providers/Microsoft.Compute'
|
||||
'/images/{name}'),
|
||||
disposition='source/managedImage/id'
|
||||
),
|
||||
replica_count=dict(
|
||||
type='int',
|
||||
disposition='replicaCount'
|
||||
),
|
||||
exclude_from_latest=dict(
|
||||
type='bool',
|
||||
disposition='excludeFromLatest'
|
||||
),
|
||||
end_of_life_date=dict(
|
||||
type='str',
|
||||
disposition='endOfLifeDate'
|
||||
),
|
||||
storage_account_type=dict(
|
||||
type='str',
|
||||
disposition='storageAccountType',
|
||||
choices=['Standard_LRS',
|
||||
'Standard_ZRS']
|
||||
)
|
||||
)
|
||||
),
|
||||
state=dict(
|
||||
type='str',
|
||||
default='present',
|
||||
choices=['present', 'absent']
|
||||
)
|
||||
)
|
||||
|
||||
self.resource_group = None
|
||||
self.gallery_name = None
|
||||
self.gallery_image_name = None
|
||||
self.name = None
|
||||
self.gallery_image_version = None
|
||||
|
||||
self.results = dict(changed=False)
|
||||
self.mgmt_client = None
|
||||
self.state = None
|
||||
self.url = None
|
||||
self.status_code = [200, 201, 202]
|
||||
self.to_do = Actions.NoAction
|
||||
|
||||
self.body = {}
|
||||
self.query_parameters = {}
|
||||
self.query_parameters['api-version'] = '2019-03-01'
|
||||
self.header_parameters = {}
|
||||
self.header_parameters['Content-Type'] = 'application/json; charset=utf-8'
|
||||
|
||||
super(AzureRMGalleryImageVersions, self).__init__(derived_arg_spec=self.module_arg_spec,
|
||||
supports_check_mode=True,
|
||||
supports_tags=True)
|
||||
|
||||
def exec_module(self, **kwargs):
|
||||
for key in list(self.module_arg_spec.keys()):
|
||||
if hasattr(self, key):
|
||||
setattr(self, key, kwargs[key])
|
||||
elif kwargs[key] is not None:
|
||||
self.body[key] = kwargs[key]
|
||||
|
||||
self.inflate_parameters(self.module_arg_spec, self.body, 0)
|
||||
|
||||
old_response = None
|
||||
response = None
|
||||
|
||||
self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient,
|
||||
base_url=self._cloud_environment.endpoints.resource_manager)
|
||||
|
||||
resource_group = self.get_resource_group(self.resource_group)
|
||||
|
||||
if 'location' not in self.body:
|
||||
self.body['location'] = resource_group.location
|
||||
|
||||
self.url = ('/subscriptions' +
|
||||
'/{{ subscription_id }}' +
|
||||
'/resourceGroups' +
|
||||
'/{{ resource_group }}' +
|
||||
'/providers' +
|
||||
'/Microsoft.Compute' +
|
||||
'/galleries' +
|
||||
'/{{ gallery_name }}' +
|
||||
'/images' +
|
||||
'/{{ image_name }}' +
|
||||
'/versions' +
|
||||
'/{{ version_name }}')
|
||||
self.url = self.url.replace('{{ subscription_id }}', self.subscription_id)
|
||||
self.url = self.url.replace('{{ resource_group }}', self.resource_group)
|
||||
self.url = self.url.replace('{{ gallery_name }}', self.gallery_name)
|
||||
self.url = self.url.replace('{{ image_name }}', self.gallery_image_name)
|
||||
self.url = self.url.replace('{{ version_name }}', self.name)
|
||||
|
||||
old_response = self.get_resource()
|
||||
|
||||
if not old_response:
|
||||
self.log("GalleryImageVersion instance doesn't exist")
|
||||
|
||||
if self.state == 'absent':
|
||||
self.log("Old instance didn't exist")
|
||||
else:
|
||||
self.to_do = Actions.Create
|
||||
else:
|
||||
self.log('GalleryImageVersion instance already exists')
|
||||
|
||||
if self.state == 'absent':
|
||||
self.to_do = Actions.Delete
|
||||
else:
|
||||
modifiers = {}
|
||||
self.create_compare_modifiers(self.module_arg_spec, '', modifiers)
|
||||
self.results['modifiers'] = modifiers
|
||||
self.results['compare'] = []
|
||||
if not self.default_compare(modifiers, self.body, old_response, '', self.results):
|
||||
self.to_do = Actions.Update
|
||||
|
||||
if (self.to_do == Actions.Create) or (self.to_do == Actions.Update):
|
||||
self.log('Need to Create / Update the GalleryImageVersion instance')
|
||||
|
||||
if self.check_mode:
|
||||
self.results['changed'] = True
|
||||
return self.results
|
||||
|
||||
response = self.create_update_resource()
|
||||
|
||||
self.results['changed'] = True
|
||||
self.log('Creation / Update done')
|
||||
elif self.to_do == Actions.Delete:
|
||||
self.log('GalleryImageVersion instance deleted')
|
||||
self.results['changed'] = True
|
||||
|
||||
if self.check_mode:
|
||||
return self.results
|
||||
|
||||
self.delete_resource()
|
||||
else:
|
||||
self.log('GalleryImageVersion instance unchanged')
|
||||
self.results['changed'] = False
|
||||
response = old_response
|
||||
|
||||
if response:
|
||||
self.results["id"] = response["id"]
|
||||
self.results["old_response"] = response
|
||||
|
||||
return self.results
|
||||
|
||||
def create_update_resource(self):
|
||||
# self.log('Creating / Updating the GalleryImageVersion instance {0}'.format(self.))
|
||||
|
||||
try:
|
||||
response = self.mgmt_client.query(self.url,
|
||||
'PUT',
|
||||
self.query_parameters,
|
||||
self.header_parameters,
|
||||
self.body,
|
||||
self.status_code,
|
||||
600,
|
||||
30)
|
||||
except CloudError as exc:
|
||||
self.log('Error attempting to create the GalleryImageVersion instance.')
|
||||
self.fail('Error creating the GalleryImageVersion instance: {0}'.format(str(exc)))
|
||||
|
||||
try:
|
||||
response = json.loads(response.text)
|
||||
except Exception:
|
||||
response = {'text': response.text}
|
||||
pass
|
||||
|
||||
while response['properties']['provisioningState'] == 'Creating':
|
||||
time.sleep(60)
|
||||
response = self.get_resource()
|
||||
|
||||
return response
|
||||
|
||||
def delete_resource(self):
|
||||
# self.log('Deleting the GalleryImageVersion instance {0}'.format(self.))
|
||||
try:
|
||||
response = self.mgmt_client.query(self.url,
|
||||
'DELETE',
|
||||
self.query_parameters,
|
||||
self.header_parameters,
|
||||
None,
|
||||
self.status_code,
|
||||
600,
|
||||
30)
|
||||
except CloudError as e:
|
||||
self.log('Error attempting to delete the GalleryImageVersion instance.')
|
||||
self.fail('Error deleting the GalleryImageVersion instance: {0}'.format(str(e)))
|
||||
return True
|
||||
|
||||
def get_resource(self):
|
||||
# self.log('Checking if the GalleryImageVersion instance {0} is present'.format(self.))
|
||||
found = False
|
||||
try:
|
||||
response = self.mgmt_client.query(self.url,
|
||||
'GET',
|
||||
self.query_parameters,
|
||||
self.header_parameters,
|
||||
None,
|
||||
self.status_code,
|
||||
600,
|
||||
30)
|
||||
response = json.loads(response.text)
|
||||
found = True
|
||||
self.log("Response : {0}".format(response))
|
||||
# self.log("AzureFirewall instance : {0} found".format(response.name))
|
||||
except CloudError as e:
|
||||
self.log('Did not find the AzureFirewall instance.')
|
||||
if found is True:
|
||||
return response
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
AzureRMGalleryImageVersions()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -20,6 +20,7 @@ options:
|
|||
description:
|
||||
- Active Directory user password. Use when authenticating with an Active Directory user rather than service
|
||||
principal.
|
||||
type: str
|
||||
profile:
|
||||
description:
|
||||
- Security profile found in ~/.azure/credentials file.
|
||||
|
|
5
test/integration/targets/azure_rm_gallery/aliases
Normal file
5
test/integration/targets/azure_rm_gallery/aliases
Normal file
|
@ -0,0 +1,5 @@
|
|||
cloud/azure
|
||||
shippable/azure/group4
|
||||
destructive
|
||||
azure_rm_galleryimage
|
||||
azure_rm_galleryimageversion
|
2
test/integration/targets/azure_rm_gallery/meta/main.yml
Normal file
2
test/integration/targets/azure_rm_gallery/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
dependencies:
|
||||
- setup_azure
|
263
test/integration/targets/azure_rm_gallery/tasks/main.yml
Normal file
263
test/integration/targets/azure_rm_gallery/tasks/main.yml
Normal file
|
@ -0,0 +1,263 @@
|
|||
- name: Prepare random number
|
||||
set_fact:
|
||||
rpfx: "{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}"
|
||||
run_once: yes
|
||||
|
||||
- name: Create virtual network
|
||||
azure_rm_virtualnetwork:
|
||||
resource_group: "{{ resource_group }}"
|
||||
name: testVnet
|
||||
address_prefixes: "10.0.0.0/16"
|
||||
|
||||
- name: Add subnet
|
||||
azure_rm_subnet:
|
||||
resource_group: "{{ resource_group }}"
|
||||
name: testSubnet
|
||||
address_prefix: "10.0.1.0/24"
|
||||
virtual_network: testVnet
|
||||
|
||||
- name: Create public IP address
|
||||
azure_rm_publicipaddress:
|
||||
resource_group: "{{ resource_group }}"
|
||||
allocation_method: Static
|
||||
name: testPublicIP
|
||||
|
||||
- name: Create virtual network inteface cards for VM A and B
|
||||
azure_rm_networkinterface:
|
||||
resource_group: "{{ resource_group }}"
|
||||
name: "vmforimage{{ rpfx }}nic"
|
||||
virtual_network: testVnet
|
||||
subnet: testSubnet
|
||||
|
||||
- name: Create VM
|
||||
azure_rm_virtualmachine:
|
||||
resource_group: "{{ resource_group }}"
|
||||
name: "vmforimage{{ rpfx }}"
|
||||
admin_username: testuser
|
||||
admin_password: "Password1234!"
|
||||
vm_size: Standard_B1ms
|
||||
network_interfaces: "vmforimage{{ rpfx }}nic"
|
||||
image:
|
||||
offer: UbuntuServer
|
||||
publisher: Canonical
|
||||
sku: 16.04-LTS
|
||||
version: latest
|
||||
- name: Generalize VM
|
||||
azure_rm_virtualmachine:
|
||||
resource_group: "{{ resource_group }}"
|
||||
name: "vmforimage{{ rpfx }}"
|
||||
generalized: yes
|
||||
- name: Create custom image
|
||||
azure_rm_image:
|
||||
resource_group: "{{ resource_group }}"
|
||||
name: testimagea
|
||||
source: "vmforimage{{ rpfx }}"
|
||||
- name: Create or update a simple gallery.
|
||||
azure_rm_gallery:
|
||||
resource_group: "{{ resource_group }}"
|
||||
name: myGallery{{ rpfx }}
|
||||
location: West US
|
||||
description: This is the gallery description.
|
||||
register: output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- output.changed
|
||||
|
||||
- name: Create or update a simple gallery - idempotent
|
||||
azure_rm_gallery:
|
||||
resource_group: "{{ resource_group }}"
|
||||
name: myGallery{{ rpfx }}
|
||||
location: West US
|
||||
description: This is the gallery description.
|
||||
register: output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not output.changed
|
||||
|
||||
- name: Create or update a simple gallery - change description
|
||||
azure_rm_gallery:
|
||||
resource_group: "{{ resource_group }}"
|
||||
name: myGallery{{ rpfx }}
|
||||
location: West US
|
||||
description: This is the gallery description - xxx.
|
||||
register: output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- output.changed
|
||||
|
||||
- name: Create or update gallery image
|
||||
azure_rm_galleryimage:
|
||||
resource_group: "{{ resource_group }}"
|
||||
gallery_name: myGallery{{ rpfx }}
|
||||
name: myImage
|
||||
location: West US
|
||||
os_type: linux
|
||||
os_state: generalized
|
||||
identifier:
|
||||
publisher: myPublisherName
|
||||
offer: myOfferName
|
||||
sku: mySkuName
|
||||
description: Image Description
|
||||
register: output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- output.changed
|
||||
|
||||
- name: Create or update gallery image - idempotent
|
||||
azure_rm_galleryimage:
|
||||
resource_group: "{{ resource_group }}"
|
||||
gallery_name: myGallery{{ rpfx }}
|
||||
name: myImage
|
||||
location: West US
|
||||
os_type: linux
|
||||
os_state: generalized
|
||||
identifier:
|
||||
publisher: myPublisherName
|
||||
offer: myOfferName
|
||||
sku: mySkuName
|
||||
description: Image Description
|
||||
register: output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not output.changed
|
||||
|
||||
- name: Create or update gallery image - change description
|
||||
azure_rm_galleryimage:
|
||||
resource_group: "{{ resource_group }}"
|
||||
gallery_name: myGallery{{ rpfx }}
|
||||
name: myImage
|
||||
location: West US
|
||||
os_type: linux
|
||||
os_state: generalized
|
||||
identifier:
|
||||
publisher: myPublisherName
|
||||
offer: myOfferName
|
||||
sku: mySkuName
|
||||
description: Image Description XXXs
|
||||
register: output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- output.changed
|
||||
|
||||
- name: Create or update a simple gallery Image Version.
|
||||
azure_rm_galleryimageversion:
|
||||
resource_group: "{{ resource_group }}"
|
||||
gallery_name: myGallery{{ rpfx }}
|
||||
gallery_image_name: myImage
|
||||
name: 10.1.3
|
||||
location: West US
|
||||
publishing_profile:
|
||||
end_of_life_date: "2020-10-01t00:00:00+00:00"
|
||||
exclude_from_latest: yes
|
||||
replica_count: 3
|
||||
storage_account_type: Standard_LRS
|
||||
target_regions:
|
||||
- name: West US
|
||||
regional_replica_count: 1
|
||||
- name: East US
|
||||
regional_replica_count: 2
|
||||
storage_account_type: Standard_ZRS
|
||||
managed_image:
|
||||
name: testimagea
|
||||
resource_group: "{{ resource_group }}"
|
||||
register: output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- output.changed
|
||||
|
||||
- name: Create or update a simple gallery Image Version - idempotent
|
||||
azure_rm_galleryimageversion:
|
||||
resource_group: "{{ resource_group }}"
|
||||
gallery_name: myGallery{{ rpfx }}
|
||||
gallery_image_name: myImage
|
||||
name: 10.1.3
|
||||
location: West US
|
||||
publishing_profile:
|
||||
end_of_life_date: "2020-10-01t00:00:00+00:00"
|
||||
exclude_from_latest: yes
|
||||
replica_count: 3
|
||||
storage_account_type: Standard_LRS
|
||||
target_regions:
|
||||
- name: West US
|
||||
regional_replica_count: 1
|
||||
- name: East US
|
||||
regional_replica_count: 2
|
||||
storage_account_type: Standard_ZRS
|
||||
managed_image:
|
||||
name: testimagea
|
||||
resource_group: "{{ resource_group }}"
|
||||
register: output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not output.changed
|
||||
|
||||
- name: Create or update a simple gallery Image Version - change end of life
|
||||
azure_rm_galleryimageversion:
|
||||
resource_group: "{{ resource_group }}"
|
||||
gallery_name: myGallery{{ rpfx }}
|
||||
gallery_image_name: myImage
|
||||
name: 10.1.3
|
||||
location: West US
|
||||
publishing_profile:
|
||||
end_of_life_date: "2021-10-01t00:00:00+00:00"
|
||||
exclude_from_latest: yes
|
||||
replica_count: 3
|
||||
storage_account_type: Standard_LRS
|
||||
target_regions:
|
||||
- name: West US
|
||||
regional_replica_count: 1
|
||||
- name: East US
|
||||
regional_replica_count: 2
|
||||
storage_account_type: Standard_ZRS
|
||||
managed_image:
|
||||
name: testimagea
|
||||
resource_group: "{{ resource_group }}"
|
||||
register: output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- output.changed
|
||||
|
||||
- name: Delete gallery image Version.
|
||||
azure_rm_galleryimageversion:
|
||||
resource_group: "{{ resource_group }}"
|
||||
gallery_name: myGallery{{ rpfx }}
|
||||
gallery_image_name: myImage
|
||||
name: 10.1.3
|
||||
state: absent
|
||||
register: output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- output.changed
|
||||
|
||||
- name: Delete gallery image
|
||||
azure_rm_galleryimage:
|
||||
resource_group: "{{ resource_group }}"
|
||||
gallery_name: myGallery{{ rpfx }}
|
||||
name: myImage
|
||||
state: absent
|
||||
register: output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- output.changed
|
||||
|
||||
- name: Delete gallery
|
||||
azure_rm_gallery:
|
||||
resource_group: "{{ resource_group }}"
|
||||
name: myGallery{{ rpfx }}
|
||||
state: absent
|
||||
register: output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- output.changed
|
|
@ -442,7 +442,6 @@ lib/ansible/modules/cloud/azure/azure_rm_loadbalancer.py E337
|
|||
lib/ansible/modules/cloud/azure/azure_rm_loganalyticsworkspace_facts.py E337
|
||||
lib/ansible/modules/cloud/azure/azure_rm_loganalyticsworkspace.py E337
|
||||
lib/ansible/modules/cloud/azure/azure_rm_manageddisk_facts.py E325
|
||||
lib/ansible/modules/cloud/azure/azure_rm_manageddisk_facts.py E337
|
||||
lib/ansible/modules/cloud/azure/azure_rm_manageddisk.py E337
|
||||
lib/ansible/modules/cloud/azure/azure_rm_mariadbconfiguration_facts.py E337
|
||||
lib/ansible/modules/cloud/azure/azure_rm_mariadbconfiguration.py E337
|
||||
|
|
Loading…
Reference in a new issue