mirror of https://github.com/ansible/ansible.git
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 docspull/58446/head
parent
eda5dd826f
commit
c9d82024c7
@ -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()
|
||||||
@ -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()
|
||||||
@ -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()
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
cloud/azure
|
||||||
|
shippable/azure/group4
|
||||||
|
destructive
|
||||||
|
azure_rm_galleryimage
|
||||||
|
azure_rm_galleryimageversion
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
dependencies:
|
||||||
|
- setup_azure
|
||||||
@ -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
|
||||||
Loading…
Reference in New Issue