From ed1334fbe39a256036810b4dde50e19cb967bc50 Mon Sep 17 00:00:00 2001
From: Yunge Zhu <37337818+yungezz@users.noreply.github.com>
Date: Thu, 11 Apr 2019 11:17:31 +0800
Subject: [PATCH] add wait_for_running option in azure_rm_rediscache module
 (#54976)

---
 .../cloud/azure/azure_rm_rediscache.py        | 51 +++++++++++++++++--
 .../azure_rm_rediscache/tasks/main.yml        | 17 +++----
 2 files changed, 55 insertions(+), 13 deletions(-)

diff --git a/lib/ansible/modules/cloud/azure/azure_rm_rediscache.py b/lib/ansible/modules/cloud/azure/azure_rm_rediscache.py
index 308189a3e86..41ccb9e7594 100644
--- a/lib/ansible/modules/cloud/azure/azure_rm_rediscache.py
+++ b/lib/ansible/modules/cloud/azure/azure_rm_rediscache.py
@@ -131,6 +131,14 @@ options:
                 choices:
                     - primary
                     - secondary
+    wait_for_provisioning:
+        description:
+            - Wait till the Azure Cache for Redis instance provisioning_state is Succeeded.
+            - It takes several minutes for Azure Cache for Redis to be provisioned ready for use after creating/updating/rebooting.
+            - Set this option to true to wait for provisioning_state. Set to false if you don't care about provisioning_state.
+            - Poll wait timeout is 60 minutes.
+        type: bool
+        default: True
     state:
       description:
         - Assert the state of the Azure Cache for Redis.
@@ -209,8 +217,8 @@ from ansible.module_utils.azure_rm_common import AzureRMModuleBase
 
 try:
     from msrestazure.azure_exceptions import CloudError
-    from msrest.polling import LROPoller
     from msrestazure.azure_operation import AzureOperationPoller
+    from msrest.polling import LROPoller
     from msrest.serialization import Model
     from azure.mgmt.redis import RedisManagementClient
     from azure.mgmt.redis.models import (RedisCreateParameters, RedisUpdateParameters, Sku)
@@ -366,6 +374,10 @@ class AzureRMRedisCaches(AzureRMModuleBase):
             regenerate_key=dict(
                 type='dict',
                 options=regenerate_key_spec
+            ),
+            wait_for_provisioning=dict(
+                type='bool',
+                default='True'
             )
         )
 
@@ -386,6 +398,10 @@ class AzureRMRedisCaches(AzureRMModuleBase):
         self.reboot = None
         self.regenerate_key = None
 
+        self.wait_for_provisioning = None
+        self.wait_for_provisioning_polling_interval_in_seconds = 30
+        self.wait_for_provisioning_polling_times = 120
+
         self.tags = None
 
         self.results = dict(
@@ -562,9 +578,12 @@ class AzureRMRedisCaches(AzureRMModuleBase):
             response = self._client.redis.create(resource_group_name=self.resource_group,
                                                  name=self.name,
                                                  parameters=params)
-            if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller):
+            if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller):
                 response = self.get_poller_result(response)
 
+            if self.wait_for_provisioning:
+                self.wait_for_redis_running()
+
         except CloudError as exc:
             self.log('Error attempting to create the Azure Cache for Redis instance.')
             self.fail(
@@ -598,9 +617,12 @@ class AzureRMRedisCaches(AzureRMModuleBase):
             response = self._client.redis.update(resource_group_name=self.resource_group,
                                                  name=self.name,
                                                  parameters=params)
-            if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller):
+            if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller):
                 response = self.get_poller_result(response)
 
+            if self.wait_for_provisioning:
+                self.wait_for_redis_running()
+
         except CloudError as exc:
             self.log('Error attempting to update the Azure Cache for Redis instance.')
             self.fail(
@@ -659,6 +681,11 @@ class AzureRMRedisCaches(AzureRMModuleBase):
                                                        name=self.name,
                                                        reboot_type=self.reboot['reboot_type'],
                                                        shard_id=self.reboot.get('shard_id'))
+            if isinstance(response, AzureOperationPoller) or isinstance(response, LROPoller):
+                response = self.get_poller_result(response)
+
+            if self.wait_for_provisioning:
+                self.wait_for_redis_running()
         except CloudError as e:
             self.log('Error attempting to force reboot the redis cache instance.')
             self.fail(
@@ -718,6 +745,24 @@ class AzureRMRedisCaches(AzureRMModuleBase):
             subnet_id = self.subnet
         return subnet_id
 
+    def wait_for_redis_running(self):
+        try:
+            response = self._client.redis.get(resource_group_name=self.resource_group, name=self.name)
+            status = response.provisioning_state
+            polling_times = 0
+
+            while polling_times < self.wait_for_provisioning_polling_times:
+                if status.lower() != "succeeded":
+                    polling_times += 1
+                    time.sleep(self.wait_for_provisioning_polling_interval_in_seconds)
+                    response = self._client.redis.get(resource_group_name=self.resource_group, name=self.name)
+                    status = response.provisioning_state
+                else:
+                    return True
+            self.fail("Azure Cache for Redis is not running after 60 mins.")
+        except CloudError as e:
+            self.fail("Failed to get Azure Cache for Redis: {0}".format(str(e)))
+
 
 def main():
     """Main execution"""
diff --git a/test/integration/targets/azure_rm_rediscache/tasks/main.yml b/test/integration/targets/azure_rm_rediscache/tasks/main.yml
index 72d46f7ad0d..dc0c61f39fe 100644
--- a/test/integration/targets/azure_rm_rediscache/tasks/main.yml
+++ b/test/integration/targets/azure_rm_rediscache/tasks/main.yml
@@ -13,6 +13,7 @@
     sku:
       name: basic
       size: C1
+    wait_for_provisioning: False
   check_mode: yes
   register: output
 
@@ -28,6 +29,7 @@
     sku:
       name: basic
       size: C1
+    wait_for_provisioning: False
   register: output
 
 - name: Assert creating redis cache
@@ -59,6 +61,7 @@
     sku:
       name: basic
       size: C1
+    wait_for_provisioning: False
   register: output
 
 - name: assert output not changed
@@ -92,6 +95,7 @@
       enable_non_ssl_port: true
       tags:
         testing: foo
+      wait_for_provisioning: True
     register: output
 
   - name: assert output changed
@@ -106,7 +110,7 @@
       sku:
         name: basic
         size: C1
-      enable_non_ssl_port: true
+      enable_non_ssl_port: True
       maxmemory_policy: allkeys_lru
       tags:
         testing: foo
@@ -126,21 +130,13 @@
         size: C1
       tags:
         testing: foo
+      wait_for_provisioning: True
     register: output
 
   - assert:
       that:
         - output.changed
 
-  - name: Wait for Redis provisioning to complete
-    azure_rm_rediscache_facts:
-        resource_group: "{{ resource_group }}"
-        name: "{{ redis_name }}"
-    register: facts
-    until: facts.rediscaches[0]['provisioning_state'] == 'Succeeded'
-    retries: 30
-    delay: 60
-
   - name: Force reboot redis cache
     azure_rm_rediscache:
       resource_group: "{{ resource_group }}"
@@ -201,6 +197,7 @@
     subnet:
       name: "{{ subnet_name }}"
       virtual_network_name: "{{ vnet_name }}"
+    wait_for_provisioning: False
   register: output
 
 - name: Assert creating redis cache