{"action":"created","comment":{"url":"https://api.github.com/repos/ansible/ansible-modules-core/pulls/comments/60665904","id":60665904,"diff_hunk":"@@ -0,0 +1,644 @@\n+#!/usr/bin/python\n+#\n+# This file is part of Ansible\n+#\n+# Ansible is free software: you can redistribute it and/or modify\n+# it under the terms of the GNU General Public License as published by\n+# the Free Software Foundation, either version 3 of the License, or\n+# (at your option) any later version.\n+#\n+# Ansible is distributed in the hope that it will be useful,\n+# but WITHOUT ANY WARRANTY; without even the implied warranty of\n+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+# GNU General Public License for more details.\n+#\n+# You should have received a copy of the GNU General Public License\n+# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n+DOCUMENTATION = '''\n+---\n+module: azure_deployment\n+\n+short_description: Create or destroy Azure Resource Manager template deployments\n+\n+version_added: \"2.1\"\n+\n+description:\n+     - \"Create or destroy Azure Resource Manager template deployments via the Azure SDK for Python.\n+       You can find some quick start templates in GitHub here https://github.com/azure/azure-quickstart-templates.\n+       For more information on Azue resource manager templates see https://azure.microsoft.com/en-us/documentation/articles/resource-group-template-deploy/.\"\n+\n+options:\n+  resource_group_name:\n+    description:\n+      - The resource group name to use or create to host the deployed template\n+    required: true\n+  location:\n+    description:\n+      - The geo-locations in which the resource group will be located.\n+    required: false\n+    default: West US\n+  state:\n+    description:\n+      - If state is \"present\", template will be created. If state is \"present\" and if deployment exists, it will be\n+        updated. If state is \"absent\", stack will be removed.\n+    default: present\n+    choices:\n+        - present\n+        - absent\n+  template:\n+    description:\n+      - A hash containing the templates inline. This parameter is mutually exclusive with 'template_link'.\n+        Either one of them is required if \"state\" parameter is \"present\".\n+    required: false\n+    default: None\n+  template_link:\n+    description:\n+      - Uri of file containing the template body. This parameter is mutually exclusive with 'template'. Either one\n+        of them is required if \"state\" parameter is \"present\".\n+    required: false\n+    default: None\n+  parameters:\n+    description:\n+      - A hash of all the required template variables for the deployment template. This parameter is mutually exclusive\n+        with 'parameters_link'. Either one of them is required if \"state\" parameter is \"present\".\n+    required: false\n+    default: None\n+  parameters_link:\n+    description:\n+      - Uri of file containing the parameters body. This parameter is mutually exclusive with 'parameters'. Either\n+        one of them is required if \"state\" parameter is \"present\".\n+    required: false\n+    default: None\n+\n+extends_documentation_fragment:\n+    - azure\n+\n+author:\n+    - David Justice (@devigned)\n+    - Laurent Mazuel (@lmazuel)\n+    - Andre Price (@obsoleted)\n+\n+'''\n+\n+EXAMPLES = '''\n+# Destroy a template deployment\n+- name: Destroy Azure Deploy\n+  azure_rm_deployment:\n+    state: absent\n+    subscription_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n+    resource_group_name: dev-ops-cle\n+\n+# Create or update a template deployment based on uris using parameter and template links\n+- name: Create Azure Deploy\n+  azure_rm_deployment:\n+    state: present\n+    resource_group_name: dev-ops-cle\n+    template_link: 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-vm-simple-linux/azuredeploy.json'\n+    parameters_link: 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-vm-simple-linux/azuredeploy.parameters.json'\n+\n+# Create or update a template deployment based on a uri to the template and parameters specified inline.\n+# This deploys a VM with SSH support for a given public key, then stores the result in 'azure_vms'. The result is then\n+# used to create a new host group. This host group is then used to wait for each instance to respond to the public IP SSH.\n+---\n+- hosts: localhost\n+  connection: local\n+  gather_facts: no\n+  tasks:\n+    - name: Destroy Azure Deploy\n+      azure_deployment:\n+        state: absent\n+        subscription_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n+        resource_group_name: dev-ops-cle\n+\n+    - name: Create Azure Deploy\n+      azure_deployment:\n+        state: present\n+        subscription_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n+        resource_group_name: dev-ops-cle\n+        parameters:\n+          newStorageAccountName:\n+            value: devopsclestorage1\n+          adminUsername:\n+            value: devopscle\n+          dnsNameForPublicIP:\n+            value: devopscleazure\n+          location:\n+            value: West US\n+          vmSize:\n+            value: Standard_A2\n+          vmName:\n+            value: ansibleSshVm\n+          sshKeyData:\n+            value: YOUR_SSH_PUBLIC_KEY\n+        template_link: 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-vm-sshkey/azuredeploy.json'\n+      register: azure\n+\n+    - name: Add new instance to host group\n+      add_host: hostname={{ item['ips'][0].public_ip }} groupname=azure_vms\n+      with_items: azure.deployment.instances\n+\n+    - hosts: azure_vms\n+      user: devopscle\n+      tasks:\n+        - name: Wait for SSH to come up\n+          wait_for: port=22 timeout=2000 state=started\n+        - name: echo the hostname of the vm\n+          shell: hostname\n+\n+# Deploy an Azure WebApp running a hello world'ish node app\n+- name: Create Azure WebApp Deployment at http://devopscleweb.azurewebsites.net/hello.js\n+  azure_deployment:\n+    state: present\n+    subscription_id: cbbdaed0-fea9-4693-bf0c-d446ac93c030\n+    resource_group_name: dev-ops-cle-webapp\n+    parameters:\n+      repoURL:\n+        value: 'https://github.com/devigned/az-roadshow-oss.git'\n+      siteName:\n+        value: devopscleweb\n+      hostingPlanName:\n+        value: someplan\n+      siteLocation:\n+        value: westus\n+      sku:\n+        value: Standard\n+    template_link: 'https://raw.githubusercontent.com/azure/azure-quickstart-templates/master/201-web-app-github-deploy/azuredeploy.json'\n+\n+# Create or update a template deployment based on an inline template and parameters\n+- name: Create Azure Deploy\n+  azure_deploy:\n+    state: present\n+    subscription_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n+    resource_group_name: dev-ops-cle\n+\n+    template:\n+      $schema: \"https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#\"\n+      contentVersion: \"1.0.0.0\"\n+      parameters:\n+        newStorageAccountName:\n+          type: \"string\"\n+          metadata:\n+            description: \"Unique DNS Name for the Storage Account where the Virtual Machine's disks will be placed.\"\n+        adminUsername:\n+          type: \"string\"\n+          metadata:\n+            description: \"User name for the Virtual Machine.\"\n+        adminPassword:\n+          type: \"securestring\"\n+          metadata:\n+            description: \"Password for the Virtual Machine.\"\n+        dnsNameForPublicIP:\n+          type: \"string\"\n+          metadata:\n+            description: \"Unique DNS Name for the Public IP used to access the Virtual Machine.\"\n+        ubuntuOSVersion:\n+          type: \"string\"\n+          defaultValue: \"14.04.2-LTS\"\n+          allowedValues:\n+            - \"12.04.5-LTS\"\n+            - \"14.04.2-LTS\"\n+            - \"15.04\"\n+          metadata:\n+            description: \"The Ubuntu version for the VM. This will pick a fully patched image of this given Ubuntu version. Allowed values: 12.04.5-LTS, 14.04.2-LTS, 15.04.\"\n+      variables:\n+        location: \"West US\"\n+        imagePublisher: \"Canonical\"\n+        imageOffer: \"UbuntuServer\"\n+        OSDiskName: \"osdiskforlinuxsimple\"\n+        nicName: \"myVMNic\"\n+        addressPrefix: \"10.0.0.0/16\"\n+        subnetName: \"Subnet\"\n+        subnetPrefix: \"10.0.0.0/24\"\n+        storageAccountType: \"Standard_LRS\"\n+        publicIPAddressName: \"myPublicIP\"\n+        publicIPAddressType: \"Dynamic\"\n+        vmStorageAccountContainerName: \"vhds\"\n+        vmName: \"MyUbuntuVM\"\n+        vmSize: \"Standard_D1\"\n+        virtualNetworkName: \"MyVNET\"\n+        vnetID: \"[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]\"\n+        subnetRef: \"[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]\"\n+      resources:\n+        -\n+          type: \"Microsoft.Storage/storageAccounts\"\n+          name: \"[parameters('newStorageAccountName')]\"\n+          apiVersion: \"2015-05-01-preview\"\n+          location: \"[variables('location')]\"\n+          properties:\n+            accountType: \"[variables('storageAccountType')]\"\n+        -\n+          apiVersion: \"2015-05-01-preview\"\n+          type: \"Microsoft.Network/publicIPAddresses\"\n+          name: \"[variables('publicIPAddressName')]\"\n+          location: \"[variables('location')]\"\n+          properties:\n+            publicIPAllocationMethod: \"[variables('publicIPAddressType')]\"\n+            dnsSettings:\n+              domainNameLabel: \"[parameters('dnsNameForPublicIP')]\"\n+        -\n+          type: \"Microsoft.Network/virtualNetworks\"\n+          apiVersion: \"2015-05-01-preview\"\n+          name: \"[variables('virtualNetworkName')]\"\n+          location: \"[variables('location')]\"\n+          properties:\n+            addressSpace:\n+              addressPrefixes:\n+                - \"[variables('addressPrefix')]\"\n+            subnets:\n+              -\n+                name: \"[variables('subnetName')]\"\n+                properties:\n+                  addressPrefix: \"[variables('subnetPrefix')]\"\n+        -\n+          type: \"Microsoft.Network/networkInterfaces\"\n+          apiVersion: \"2015-05-01-preview\"\n+          name: \"[variables('nicName')]\"\n+          location: \"[variables('location')]\"\n+          dependsOn:\n+            - \"[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]\"\n+            - \"[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]\"\n+          properties:\n+            ipConfigurations:\n+              -\n+                name: \"ipconfig1\"\n+                properties:\n+                  privateIPAllocationMethod: \"Dynamic\"\n+                  publicIPAddress:\n+                    id: \"[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]\"\n+                  subnet:\n+                    id: \"[variables('subnetRef')]\"\n+        -\n+          type: \"Microsoft.Compute/virtualMachines\"\n+          apiVersion: \"2015-06-15\"\n+          name: \"[variables('vmName')]\"\n+          location: \"[variables('location')]\"\n+          dependsOn:\n+            - \"[concat('Microsoft.Storage/storageAccounts/', parameters('newStorageAccountName'))]\"\n+            - \"[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]\"\n+          properties:\n+            hardwareProfile:\n+              vmSize: \"[variables('vmSize')]\"\n+            osProfile:\n+              computername: \"[variables('vmName')]\"\n+              adminUsername: \"[parameters('adminUsername')]\"\n+              adminPassword: \"[parameters('adminPassword')]\"\n+            storageProfile:\n+              imageReference:\n+                publisher: \"[variables('imagePublisher')]\"\n+                offer: \"[variables('imageOffer')]\"\n+                sku: \"[parameters('ubuntuOSVersion')]\"\n+                version: \"latest\"\n+              osDisk:\n+                name: \"osdisk\"\n+                vhd:\n+                  uri: \"[concat('http://',parameters('newStorageAccountName'),'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/',variables('OSDiskName'),'.vhd')]\"\n+                caching: \"ReadWrite\"\n+                createOption: \"FromImage\"\n+            networkProfile:\n+              networkInterfaces:\n+                -\n+                  id: \"[resourceId('Microsoft.Network/networkInterfaces',variables('nicName'))]\"\n+            diagnosticsProfile:\n+              bootDiagnostics:\n+                enabled: \"true\"\n+                storageUri: \"[concat('http://',parameters('newStorageAccountName'),'.blob.core.windows.net')]\"\n+    parameters:\n+      newStorageAccountName:\n+        value: devopsclestorage\n+      adminUsername:\n+        value: devopscle\n+      adminPassword:\n+        value: Password1!\n+      dnsNameForPublicIP:\n+        value: devopscleazure\n+'''\n+\n+RETURN = '''\n+msg:\n+  description: String indicating if the deployment was created or deleted\n+  returned: always\n+  type: string\n+  sample: \"deployment created\"\n+deployment:\n+  description: Deployment details\n+  type: dict\n+  returned: always\n+  sample:{\n+        \"group_name\": \"Test_Deployment\",\n+        \"id\": \"/subscriptions/3f7e29ba-24e0-42f6-8d9c-5149a14bda37/resourceGroups/Test_Deployment/providers/Microsoft.Resources/deployments/ansible-arm\",\n+        \"instances\": [\n+            {\n+                \"ips\": [\n+                    {\n+                        \"dns_settings\": {\n+                            \"domain_name_label\": \"testvm9910001\",\n+                            \"fqdn\": \"testvm9910001.westus.cloudapp.azure.com\"\n+                        },\n+                        \"id\": \"/subscriptions/3f7e29ba-24e0-42f6-8d9c-5149a14bda37/resourceGroups/Test_Deployment/providers/Microsoft.Network/publicIPAddresses/myPublicIP\",\n+                        \"name\": \"myPublicIP\",\n+                        \"public_ip\": \"13.91.99.232\",\n+                        \"public_ip_allocation_method\": \"IPAllocationMethod.dynamic\"\n+                    }\n+                ],\n+                \"vm_name\": \"MyUbuntuVM\"\n+            }\n+        ],\n+        \"name\": \"ansible-arm\",\n+        \"outputs\": {\n+            \"hostname\": {\n+                \"type\": \"String\",\n+                \"value\": \"testvm9910001.westus.cloudapp.azure.com\"\n+            },\n+            \"sshCommand\": {\n+                \"type\": \"String\",\n+                \"value\": \"ssh chouseknecht@testvm9910001.westus.cloudapp.azure.com\"\n+            }\n+        }\n+    }\n+'''\n+\n+import time\n+import yaml\n+\n+from ansible.module_utils.basic import *\n+from ansible.module_utils.azure_rm_common import *\n+\n+try:\n+    from itertools import chain\n+    from azure.common.credentials import ServicePrincipalCredentials\n+    from azure.common.exceptions import CloudError\n+    from azure.mgmt.resource.resources.models import (DeploymentProperties,\n+                                                      ParametersLink,\n+                                                      TemplateLink,\n+                                                      Deployment,\n+                                                      ResourceGroup,\n+                                                      Dependency)\n+    from azure.mgmt.resource.resources import ResourceManagementClient, ResourceManagementClientConfiguration\n+    from azure.mgmt.network import NetworkManagementClient, NetworkManagementClientConfiguration\n+\n+except ImportError:\n+    # This is handled in azure_rm_common\n+    pass\n+\n+\n+class AzureRMDeploymentManager(AzureRMModuleBase):\n+\n+    def __init__(self):\n+\n+        self.module_arg_spec = dict(\n+            resource_group_name=dict(type='str', required=True, aliases=['resource_group']),\n+            state=dict(type='str', default='present', choices=['present', 'absent']),\n+            template=dict(type='dict', default=None),\n+            parameters=dict(type='dict', default=None),\n+            template_link=dict(type='str', default=None),\n+            parameters_link=dict(type='str', default=None),\n+            location=dict(type='str', default=\"West US\"),\n+            deployment_mode=dict(type='str', default='Complete', choices=['Complete', 'Incremental']),\n+            deployment_name=dict(type='str', default=\"ansible-arm\"),\n+            wait_for_deployment_completion=dict(type='bool', default=True),\n+            wait_for_deployment_polling_period=dict(type='int', default=30)\n+        )\n+\n+        mutually_exclusive = [('template', 'template_link'),\n+                              ('parameters', 'parameters_link')]\n+\n+        self.resource_group_name = None\n+        self.state = None\n+        self.template = None\n+        self.parameters = None\n+        self.template_link = None\n+        self.parameters_link = None\n+        self.location = None\n+        self.deployment_mode = None\n+        self.deployment_name = None\n+        self.wait_for_deployment_completion = None\n+        self.wait_for_deployment_polling_period = None\n+        self.tags = None\n+\n+        self.results = dict(\n+            deployment=dict(),\n+            changed=False,\n+            msg=\"\"\n+        )\n+\n+        super(AzureRMDeploymentManager, self).__init__(derived_arg_spec=self.module_arg_spec,\n+                                                       mutually_exclusive=mutually_exclusive,\n+                                                       supports_check_mode=False)\n+\n+    def exec_module(self, **kwargs):\n+\n+        for key in self.module_arg_spec.keys() + ['tags']:\n+            setattr(self, key, kwargs[key])\n+\n+        if self.state == 'present':\n+            deployment = self.deploy_template()\n+            self.results['deployment'] = dict(\n+                name=deployment.name,\n+                group_name=self.resource_group_name,\n+                id=deployment.id,\n+                outputs=deployment.properties.outputs,\n+                instances=self._get_instances(deployment)\n+            )\n+            self.results['changed'] = True\n+            self.results['msg'] = 'deployment created'\n+        else:\n+            if self.resource_group_exists(self.resource_group_name):\n+                self.destroy_resource_group()\n+                self.results['changed'] = True\n+                self.results['msg'] = \"deployment deleted\"\n+\n+        return self.results\n+\n+    def deploy_template(self):\n+        \"\"\"\n+        Deploy the targeted template and parameters\n+        :param module: Ansible module containing the validated configuration for the deployment template\n+        :param client: resource management client for azure\n+        :param conn_info: connection info needed\n+        :return:\n+        \"\"\"\n+\n+        deploy_parameter = DeploymentProperties()\n+        deploy_parameter.mode = self.deployment_mode\n+        if not self.parameters_link:\n+            deploy_parameter.parameters = self.parameters\n+        else:\n+            deploy_parameter.parameters_link = ParametersLink(\n+                uri=self.parameters_link\n+            )\n+        if not self.template_link:\n+            deploy_parameter.template = self.template\n+        else:\n+            deploy_parameter.template_link = TemplateLink(\n+                uri=self.template_link\n+            )\n+\n+        params = ResourceGroup(location=self.location, tags=self.tags)\n+\n+        try:\n+            self.rm_client.resource_groups.create_or_update(self.resource_group_name, params)\n+        except CloudError as exc:\n+            self.fail(\"Resource group create_or_update failed with status code: %s and message: %s\" %\n+                      (exc.status_code, exc.message))\n+        try:\n+            result = self.rm_client.deployments.create_or_update(self.resource_group_name,\n+                                                                 self.deployment_name,\n+                                                                 deploy_parameter)\n+\n+            deployment_result = self.get_poller_result(result)\n+            if self.wait_for_deployment_completion:\n+                while deployment_result.properties.provisioning_state not in ['Canceled', 'Failed', 'Deleted',\n+                                                                              'Succeeded']:\n+                    time.sleep(self.wait_for_deployment_polling_period)\n+                    deployment_result = self.rm_client.deployments.get(self.resource_group_name, self.deployment_name)\n+        except CloudError as exc:\n+            failed_deployment_operations = self._get_failed_deployment_operations(self.deployment_name)\n+            self.fail(\"Deployment failed with status code: %s and message: %s\" % (exc.status_code, exc.message),\n+                      failed_deployment_operations=failed_deployment_operations)\n+\n+        if self.wait_for_deployment_completion and deployment_result.properties.provisioning_state != 'Succeeded':\n+            self.log(\"provisioning state: %s\" % deployment_result.properties.provisioning_state)\n+            failed_deployment_operations = self._get_failed_deployment_operations(self.deployment_name)\n+            self.fail('Deployment failed. Deployment id: %s' % deployment_result.id,\n+                      failed_deployment_operations=failed_deployment_operations)\n+        return deployment_result\n+\n+    def destroy_resource_group(self):\n+        \"\"\"\n+        Destroy the targeted resource group\n+        \"\"\"\n+        try:\n+            result = self.rm_client.resource_groups.delete(self.resource_group_name)\n+            result.wait() # Blocking wait till the delete is finished\n+        except CloudError as e:\n+            if e.status_code == 404 or e.status_code == 204:\n+                return\n+            else:\n+                self.fail(\"Delete resource group and deploy failed with status code: %s and message: %s\" %\n+                          (e.status_code, e.message))\n+\n+    def resource_group_exists(self, resource_group):\n+        '''\n+        Return True/False based on existence of requested resource group.\n+\n+        :param resource_group: string. Name of a resource group.\n+        :return: boolean\n+        '''\n+        try:\n+            self.rm_client.resource_groups.get(resource_group)\n+        except CloudError:\n+            return False\n+        return True\n+\n+    def _get_failed_nested_operations(self, current_operations):\n+        new_operations = []\n+        for operation in current_operations:\n+            if operation.properties.provisioning_state == 'Failed':\n+                new_operations.append(operation)\n+                if operation.properties.target_resource and \\\n+                   'Microsoft.Resources/deployments' in operation.properties.target_resource.id:\n+                    nested_deployment = operation.properties.target_resource.resource_name\n+                    try:\n+                        nested_operations = self.rm_client.deployment_operations.list(self.resource_group_name,\n+                                                                                      nested_deployment)\n+                    except CloudError as exc:\n+                        self.fail(\"List nested deployment operations failed with status code: %s and message: %s\" %\n+                                 (e.status_code, e.message))\n+                    new_nested_operations = self._get_failed_nested_operations(nested_operations)\n+                    new_operations += new_nested_operations\n+        return new_operations\n+\n+    def _get_failed_deployment_operations(self, deployment_name):\n+        results = []\n+        # time.sleep(15) # there is a race condition between when we ask for deployment status and when the\n+        #               # status is available.\n+\n+        try:\n+            operations = self.rm_client.deployment_operations.list(self.resource_group_name, deployment_name)\n+        except CloudError as exc:\n+            self.fail(\"Get deployment failed with status code: %s and message: %s\" %\n+                      (exc.status_code, exc.message))\n+        try:\n+            results = [\n+                dict(\n+                    id=op.id,\n+                    operation_id=op.operation_id,\n+                    status_code=op.properties.status_code,\n+                    status_message=op.properties.status_message,\n+                    target_resource=dict(\n+                        id=op.properties.target_resource.id,\n+                        resource_name=op.properties.target_resource.resource_name,\n+                        resource_type=op.properties.target_resource.resource_type\n+                    ) if op.properties.target_resource else None,\n+                    provisioning_state=op.properties.provisioning_state,\n+                )\n+                for op in self._get_failed_nested_operations(operations)\n+            ]\n+        except:\n+            # If we fail here, the original error gets lost and user receives wrong error message/stacktrace","path":"cloud/azure/azure_rm_deployment.py","position":578,"original_position":578,"commit_id":"3bebbbde134563e1eb0fcf9fd510d5d3d55a0548","original_commit_id":"3bebbbde134563e1eb0fcf9fd510d5d3d55a0548","user":{"login":"nitzmahone","id":6775756,"avatar_url":"https://avatars.githubusercontent.com/u/6775756?v=3","gravatar_id":"","url":"https://api.github.com/users/nitzmahone","html_url":"https://github.com/nitzmahone","followers_url":"https://api.github.com/users/nitzmahone/followers","following_url":"https://api.github.com/users/nitzmahone/following{/other_user}","gists_url":"https://api.github.com/users/nitzmahone/gists{/gist_id}","starred_url":"https://api.github.com/users/nitzmahone/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nitzmahone/subscriptions","organizations_url":"https://api.github.com/users/nitzmahone/orgs","repos_url":"https://api.github.com/users/nitzmahone/repos","events_url":"https://api.github.com/users/nitzmahone/events{/privacy}","received_events_url":"https://api.github.com/users/nitzmahone/received_events","type":"User","site_admin":false},"body":"should probably at least try to log this failure (to our neutered log, but still)","created_at":"2016-04-21T22:32:54Z","updated_at":"2016-04-21T22:32:54Z","html_url":"https://github.com/ansible/ansible-modules-core/pull/3513#discussion_r60665904","pull_request_url":"https://api.github.com/repos/ansible/ansible-modules-core/pulls/3513","_links":{"self":{"href":"https://api.github.com/repos/ansible/ansible-modules-core/pulls/comments/60665904"},"html":{"href":"https://github.com/ansible/ansible-modules-core/pull/3513#discussion_r60665904"},"pull_request":{"href":"https://api.github.com/repos/ansible/ansible-modules-core/pulls/3513"}}},"pull_request":{"url":"https://api.github.com/repos/ansible/ansible-modules-core/pulls/3513","id":67431310,"html_url":"https://github.com/ansible/ansible-modules-core/pull/3513","diff_url":"https://github.com/ansible/ansible-modules-core/pull/3513.diff","patch_url":"https://github.com/ansible/ansible-modules-core/pull/3513.patch","issue_url":"https://api.github.com/repos/ansible/ansible-modules-core/issues/3513","number":3513,"state":"open","locked":false,"title":"Refactored azure_deploy module","user":{"login":"chouseknecht","id":1282865,"avatar_url":"https://avatars.githubusercontent.com/u/1282865?v=3","gravatar_id":"","url":"https://api.github.com/users/chouseknecht","html_url":"https://github.com/chouseknecht","followers_url":"https://api.github.com/users/chouseknecht/followers","following_url":"https://api.github.com/users/chouseknecht/following{/other_user}","gists_url":"https://api.github.com/users/chouseknecht/gists{/gist_id}","starred_url":"https://api.github.com/users/chouseknecht/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chouseknecht/subscriptions","organizations_url":"https://api.github.com/users/chouseknecht/orgs","repos_url":"https://api.github.com/users/chouseknecht/repos","events_url":"https://api.github.com/users/chouseknecht/events{/privacy}","received_events_url":"https://api.github.com/users/chouseknecht/received_events","type":"User","site_admin":false},"body":"##### ISSUE TYPE\r\n - New Module Pull Request\r\n\r\n##### COMPONENT NAME\r\nazure_rm_deployment\r\n\r\n##### ANSIBLE VERSION\r\n```\r\nansible 2.1.0 (azure_common a79e9182e1) last updated 2016/04/21 17:52:27 (GMT -400)\r\n  lib/ansible/modules/core: (devel 67de0675c3) last updated 2016/04/21 14:30:20 (GMT -400)\r\n  lib/ansible/modules/extras: (devel 247e17a665) last updated 2016/04/21 14:27:29 (GMT -400)\r\n  config file = /Users/chouseknecht/projects/azure/azurerm/test/ansible.cfg\r\n  configured module search path = Default w/o overrides\r\n```\r\n\r\n##### SUMMARY\r\nMoving the azure_deploy module from extras to core. azure_deploy was submitted by MS. The refactored version uses azure_rm_common and fits the pattern followed by the other azure_rm_* modules.","created_at":"2016-04-21T22:16:06Z","updated_at":"2016-04-21T22:32:54Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c77ca4140a1eb495d746b420f73b1d876392272f","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ansible/ansible-modules-core/pulls/3513/commits","review_comments_url":"https://api.github.com/repos/ansible/ansible-modules-core/pulls/3513/comments","review_comment_url":"https://api.github.com/repos/ansible/ansible-modules-core/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ansible/ansible-modules-core/issues/3513/comments","statuses_url":"https://api.github.com/repos/ansible/ansible-modules-core/statuses/3bebbbde134563e1eb0fcf9fd510d5d3d55a0548","head":{"label":"chouseknecht:azure_rm_deployment","ref":"azure_rm_deployment","sha":"3bebbbde134563e1eb0fcf9fd510d5d3d55a0548","user":{"login":"chouseknecht","id":1282865,"avatar_url":"https://avatars.githubusercontent.com/u/1282865?v=3","gravatar_id":"","url":"https://api.github.com/users/chouseknecht","html_url":"https://github.com/chouseknecht","followers_url":"https://api.github.com/users/chouseknecht/followers","following_url":"https://api.github.com/users/chouseknecht/following{/other_user}","gists_url":"https://api.github.com/users/chouseknecht/gists{/gist_id}","starred_url":"https://api.github.com/users/chouseknecht/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chouseknecht/subscriptions","organizations_url":"https://api.github.com/users/chouseknecht/orgs","repos_url":"https://api.github.com/users/chouseknecht/repos","events_url":"https://api.github.com/users/chouseknecht/events{/privacy}","received_events_url":"https://api.github.com/users/chouseknecht/received_events","type":"User","site_admin":false},"repo":{"id":56418528,"name":"ansible-modules-core","full_name":"chouseknecht/ansible-modules-core","owner":{"login":"chouseknecht","id":1282865,"avatar_url":"https://avatars.githubusercontent.com/u/1282865?v=3","gravatar_id":"","url":"https://api.github.com/users/chouseknecht","html_url":"https://github.com/chouseknecht","followers_url":"https://api.github.com/users/chouseknecht/followers","following_url":"https://api.github.com/users/chouseknecht/following{/other_user}","gists_url":"https://api.github.com/users/chouseknecht/gists{/gist_id}","starred_url":"https://api.github.com/users/chouseknecht/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chouseknecht/subscriptions","organizations_url":"https://api.github.com/users/chouseknecht/orgs","repos_url":"https://api.github.com/users/chouseknecht/repos","events_url":"https://api.github.com/users/chouseknecht/events{/privacy}","received_events_url":"https://api.github.com/users/chouseknecht/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/chouseknecht/ansible-modules-core","description":"Ansible modules - these modules ship with ansible","fork":true,"url":"https://api.github.com/repos/chouseknecht/ansible-modules-core","forks_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/forks","keys_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/keys{/key_id}","collaborators_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/teams","hooks_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/hooks","issue_events_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/issues/events{/number}","events_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/events","assignees_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/assignees{/user}","branches_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/branches{/branch}","tags_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/tags","blobs_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/git/refs{/sha}","trees_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/git/trees{/sha}","statuses_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/statuses/{sha}","languages_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/languages","stargazers_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/stargazers","contributors_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/contributors","subscribers_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/subscribers","subscription_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/subscription","commits_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/commits{/sha}","git_commits_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/git/commits{/sha}","comments_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/comments{/number}","issue_comment_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/issues/comments{/number}","contents_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/contents/{+path}","compare_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/compare/{base}...{head}","merges_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/merges","archive_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/downloads","issues_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/issues{/number}","pulls_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/pulls{/number}","milestones_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/milestones{/number}","notifications_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/labels{/name}","releases_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/releases{/id}","deployments_url":"https://api.github.com/repos/chouseknecht/ansible-modules-core/deployments","created_at":"2016-04-17T04:14:25Z","updated_at":"2016-04-17T04:14:28Z","pushed_at":"2016-04-21T22:13:44Z","git_url":"git://github.com/chouseknecht/ansible-modules-core.git","ssh_url":"git@github.com:chouseknecht/ansible-modules-core.git","clone_url":"https://github.com/chouseknecht/ansible-modules-core.git","svn_url":"https://github.com/chouseknecht/ansible-modules-core","homepage":"","size":7928,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"devel"}},"base":{"label":"ansible:devel","ref":"devel","sha":"804a8e637874ffe404b12b3a05305d147168f605","user":{"login":"ansible","id":1507452,"avatar_url":"https://avatars.githubusercontent.com/u/1507452?v=3","gravatar_id":"","url":"https://api.github.com/users/ansible","html_url":"https://github.com/ansible","followers_url":"https://api.github.com/users/ansible/followers","following_url":"https://api.github.com/users/ansible/following{/other_user}","gists_url":"https://api.github.com/users/ansible/gists{/gist_id}","starred_url":"https://api.github.com/users/ansible/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ansible/subscriptions","organizations_url":"https://api.github.com/users/ansible/orgs","repos_url":"https://api.github.com/users/ansible/repos","events_url":"https://api.github.com/users/ansible/events{/privacy}","received_events_url":"https://api.github.com/users/ansible/received_events","type":"Organization","site_admin":false},"repo":{"id":24474126,"name":"ansible-modules-core","full_name":"ansible/ansible-modules-core","owner":{"login":"ansible","id":1507452,"avatar_url":"https://avatars.githubusercontent.com/u/1507452?v=3","gravatar_id":"","url":"https://api.github.com/users/ansible","html_url":"https://github.com/ansible","followers_url":"https://api.github.com/users/ansible/followers","following_url":"https://api.github.com/users/ansible/following{/other_user}","gists_url":"https://api.github.com/users/ansible/gists{/gist_id}","starred_url":"https://api.github.com/users/ansible/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ansible/subscriptions","organizations_url":"https://api.github.com/users/ansible/orgs","repos_url":"https://api.github.com/users/ansible/repos","events_url":"https://api.github.com/users/ansible/events{/privacy}","received_events_url":"https://api.github.com/users/ansible/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ansible/ansible-modules-core","description":"Ansible modules - these modules ship with ansible","fork":false,"url":"https://api.github.com/repos/ansible/ansible-modules-core","forks_url":"https://api.github.com/repos/ansible/ansible-modules-core/forks","keys_url":"https://api.github.com/repos/ansible/ansible-modules-core/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ansible/ansible-modules-core/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ansible/ansible-modules-core/teams","hooks_url":"https://api.github.com/repos/ansible/ansible-modules-core/hooks","issue_events_url":"https://api.github.com/repos/ansible/ansible-modules-core/issues/events{/number}","events_url":"https://api.github.com/repos/ansible/ansible-modules-core/events","assignees_url":"https://api.github.com/repos/ansible/ansible-modules-core/assignees{/user}","branches_url":"https://api.github.com/repos/ansible/ansible-modules-core/branches{/branch}","tags_url":"https://api.github.com/repos/ansible/ansible-modules-core/tags","blobs_url":"https://api.github.com/repos/ansible/ansible-modules-core/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ansible/ansible-modules-core/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ansible/ansible-modules-core/git/refs{/sha}","trees_url":"https://api.github.com/repos/ansible/ansible-modules-core/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ansible/ansible-modules-core/statuses/{sha}","languages_url":"https://api.github.com/repos/ansible/ansible-modules-core/languages","stargazers_url":"https://api.github.com/repos/ansible/ansible-modules-core/stargazers","contributors_url":"https://api.github.com/repos/ansible/ansible-modules-core/contributors","subscribers_url":"https://api.github.com/repos/ansible/ansible-modules-core/subscribers","subscription_url":"https://api.github.com/repos/ansible/ansible-modules-core/subscription","commits_url":"https://api.github.com/repos/ansible/ansible-modules-core/commits{/sha}","git_commits_url":"https://api.github.com/repos/ansible/ansible-modules-core/git/commits{/sha}","comments_url":"https://api.github.com/repos/ansible/ansible-modules-core/comments{/number}","issue_comment_url":"https://api.github.com/repos/ansible/ansible-modules-core/issues/comments{/number}","contents_url":"https://api.github.com/repos/ansible/ansible-modules-core/contents/{+path}","compare_url":"https://api.github.com/repos/ansible/ansible-modules-core/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ansible/ansible-modules-core/merges","archive_url":"https://api.github.com/repos/ansible/ansible-modules-core/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ansible/ansible-modules-core/downloads","issues_url":"https://api.github.com/repos/ansible/ansible-modules-core/issues{/number}","pulls_url":"https://api.github.com/repos/ansible/ansible-modules-core/pulls{/number}","milestones_url":"https://api.github.com/repos/ansible/ansible-modules-core/milestones{/number}","notifications_url":"https://api.github.com/repos/ansible/ansible-modules-core/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ansible/ansible-modules-core/labels{/name}","releases_url":"https://api.github.com/repos/ansible/ansible-modules-core/releases{/id}","deployments_url":"https://api.github.com/repos/ansible/ansible-modules-core/deployments","created_at":"2014-09-25T20:28:25Z","updated_at":"2016-04-21T07:15:12Z","pushed_at":"2016-04-21T22:16:06Z","git_url":"git://github.com/ansible/ansible-modules-core.git","ssh_url":"git@github.com:ansible/ansible-modules-core.git","clone_url":"https://github.com/ansible/ansible-modules-core.git","svn_url":"https://github.com/ansible/ansible-modules-core","homepage":"","size":14658,"stargazers_count":656,"watchers_count":656,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1488,"mirror_url":null,"open_issues_count":1025,"forks":1488,"open_issues":1025,"watchers":656,"default_branch":"devel"}},"_links":{"self":{"href":"https://api.github.com/repos/ansible/ansible-modules-core/pulls/3513"},"html":{"href":"https://github.com/ansible/ansible-modules-core/pull/3513"},"issue":{"href":"https://api.github.com/repos/ansible/ansible-modules-core/issues/3513"},"comments":{"href":"https://api.github.com/repos/ansible/ansible-modules-core/issues/3513/comments"},"review_comments":{"href":"https://api.github.com/repos/ansible/ansible-modules-core/pulls/3513/comments"},"review_comment":{"href":"https://api.github.com/repos/ansible/ansible-modules-core/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ansible/ansible-modules-core/pulls/3513/commits"},"statuses":{"href":"https://api.github.com/repos/ansible/ansible-modules-core/statuses/3bebbbde134563e1eb0fcf9fd510d5d3d55a0548"}}}}