Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New modules for webapp vnet connection #590

Merged
merged 23 commits into from
Aug 13, 2021
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0d8a3eb
info module for webapp vnetintegration
l3ender Aug 3, 2021
6f3b094
add module for configuring vnet connection
l3ender Aug 3, 2021
458e573
add coverage for webapp vnetconnection module
l3ender Aug 3, 2021
0950354
add doc/examples
l3ender Aug 3, 2021
39de2b5
add delete idempotent test for webpp vnetconnection
l3ender Aug 3, 2021
3cf3edc
Merge remote-tracking branch 'upstream/dev' into webapp-vnet-integration
l3ender Aug 3, 2021
28e68d5
formatting
l3ender Aug 3, 2021
fa0acf0
formatting and logging
l3ender Aug 4, 2021
1ddd288
Merge branch 'dev' into webapp-vnet-integration
l3ender Aug 5, 2021
546fc9a
Apply suggestions from code review
l3ender Aug 5, 2021
992f706
Merge remote-tracking branch 'refs/remotes/origin/webapp-vnet-integra…
l3ender Aug 5, 2021
50922c5
rename module for collection consistency
l3ender Aug 6, 2021
e77260b
correct import location and line lengths
l3ender Aug 6, 2021
dcea73d
__future__ imports needed at top
l3ender Aug 6, 2021
3bd7b6c
add tests for _info module; add to asserts on main module tests
l3ender Aug 6, 2021
fcc75ad
add new module to build/test pipeline
l3ender Aug 6, 2021
7377f1c
clearer test names
l3ender Aug 6, 2021
72a54bf
Merge branch 'dev' into webapp-vnet-integration
l3ender Aug 6, 2021
a10992a
Apply suggestions from code review
l3ender Aug 10, 2021
1ff7b6e
Merge branch 'dev' into webapp-vnet-integration
Fred-sun Aug 11, 2021
0e37563
Update plugins/modules/azure_rm_webappvnetconnection_info.py
l3ender Aug 11, 2021
12c2429
Merge branch 'dev' into webapp-vnet-integration
Fred-sun Aug 12, 2021
bcfbfe9
Merge branch 'dev' into webapp-vnet-integration
l3ender Aug 12, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions plugins/module_utils/azure_rm_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,14 @@ def get_data_svc_client(self, **kwags):
config = self.add_user_agent(config)
return ServiceClient(creds=config.credentials, config=config)

def get_subnet_detail(self, subnet_id):
vnet_detail = subnet_id.split('/Microsoft.Network/virtualNetworks/')[1].split('/subnets/')
return dict(
resource_group=subnet_id.split('resourceGroups/')[1].split('/')[0],
vnet_name=vnet_detail[0],
subnet_name=vnet_detail[1],
)

# passthru methods to AzureAuth instance for backcompat
@property
def credentials(self):
Expand Down
259 changes: 259 additions & 0 deletions plugins/modules/azure_rm_webappvnetconnection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
#!/usr/bin/python
#
# Copyright (c) 2021 Ross Bender (@l3ender)
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function
__metaclass__ = type


DOCUMENTATION = '''
---
module: azure_rm_webappvnetconnection
version_added: "1.9.0"
l3ender marked this conversation as resolved.
Show resolved Hide resolved
short_description: Manage web app virtual network connection
description:
- Add, remove, or update the virtual network connection for a web app.
options:
name:
description:
- Name of the web app.
required: true
type: str
resource_group:
description:
- Resource group of the web app.
required: true
type: str
state:
description:
- State of the virtual network connection. Use C(present) to create or update and C(absent) to delete.
type: str
default: present
choices:
- absent
- present
vnet_name:
description:
- Name of the virtual network. Required if adding or updating.
type: str
subnet:
description:
- Name of the virtual network's subnet. Required if adding or updating.
type: str
vnet_resource_group:
description:
- Name of the resource group for the virtual network. Defaults to main C(resource_group) value.
type: str

extends_documentation_fragment:
- azure.azcollection.azure

author:
- Ross Bender (@l3ender)
'''

EXAMPLES = '''
- name: Configure web app with virtual network
azure.azcollection.azure_rm_webappvnetconnection:
name: "MyWebapp"
resource_group: "MyResourceGroup"
vnet_name: "MyVnetName"
subnet: "MySubnetName"

- name: Configure web app with virtual network in different resource group
azure.azcollection.azure_rm_webappvnetconnection:
name: "MyWebapp"
resource_group: "MyResourceGroup"
vnet_name: "MyVnetName"
subnet: "MySubnetName"
vnet_resource_group: "MyOtherResourceGroup"

- name: Delete web app virtual network
azure.azcollection.azure_rm_webappvnetconnection:
name: "MyWebapp"
resource_group: "MyResourceGroup"
state: "absent"
'''

RETURN = '''
connection:
description:
- The web app's virtual network connection.
returned: always
type: complex
contains:
id:
description:
- ID of the web app virtual network connection.
returned: always
type: str
sample: /subscriptions/xxx-xxx/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/myWebApp/virtualNetworkConnections/yyy-yyy_subnet
name:
description:
- Name of the web app virtual network connection.
returned: always
type: str
sample: yyy-yyy_subnet
subnet_name:
description:
- Name of the subnet connected to the web app.
returned: always
type: str
sample: mySubnet
vnet_name:
description:
- Name of the virtual network connected to the web app.
returned: always
type: str
sample: myVnet
vnet_resource_group:
description:
- Name of the resource group the virtual network is in.
returned: always
type: str
sample: myResourceGroup
vnet_resource_id:
description:
- ID of the virtual network/subnet connected to the web app.
returned: always
type: str
sample: /subscriptions/xxx-xxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/mySubnet
'''

from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase

try:
from azure.mgmt.web.models import SwiftVirtualNetwork
except Exception:
# This is handled in azure_rm_common
pass


class AzureRMWebAppVnetConnection(AzureRMModuleBase):

def __init__(self):

self.module_arg_spec = dict(
name=dict(type='str', required=True),
resource_group=dict(type='str', required=True),
state=dict(type='str', default='present', choices=['present', 'absent']),
vnet_name=dict(type='str'),
subnet=dict(type='str'),
vnet_resource_group=dict(type='str'),
)

self.results = dict(
changed=False,
connection=dict(),
)

self.state = None
self.name = None
self.resource_group = None
self.vnet_name = None
self.subnet = None
self.vnet_resource_group = None

super(AzureRMWebAppVnetConnection, self).__init__(self.module_arg_spec,
supports_check_mode=True,
supports_tags=False)

def exec_module(self, **kwargs):
for key in self.module_arg_spec:
setattr(self, key, kwargs[key])

changed = False
vnet = self.get_vnet_connection()
if vnet:
self.results['connection'] = self.set_results(vnet)

if self.state == 'absent' and vnet:
changed = True
if not self.check_mode:
self.log('Deleting vnet connection for webapp {0}'.format(self.name))
self.delete_vnet_connection()
self.results['connection'] = dict()
elif self.state == 'present':
self.vnet_resource_group = self.vnet_resource_group or self.resource_group

if not vnet:
self.log('Adding vnet connection for webapp {0}'.format(self.name))
changed = True
else:
subnet_detail = self.get_subnet_detail(vnet.vnet_resource_id)
if (subnet_detail['resource_group'] != self.vnet_resource_group
or subnet_detail['vnet_name'] != self.vnet_name
or subnet_detail['subnet_name'] != self.subnet):
self.log('Detected change in vnet connection for webapp {0}'.format(self.name))
changed = True

if changed:
if not self.check_mode:
self.log('Updating vnet connection for webapp {0}'.format(self.name))
subnet = self.get_subnet()
param = SwiftVirtualNetwork(subnet_resource_id=subnet.id)
self.create_or_update_vnet_connection(param)
vnet = self.get_vnet_connection()
self.results['connection'] = self.set_results(vnet)

self.results['changed'] = changed
return self.results

def get_vnet_connection(self):
connections = self.list_vnet_connections()
for connection in connections:
if connection.is_swift:
return connection

return None

def list_vnet_connections(self):
try:
return self.web_client.web_apps.list_vnet_connections(resource_group_name=self.resource_group, name=self.name)
except Exception as exc:
self.fail("Error getting webapp vnet connections {0} (rg={1}) - {2}".format(self.name, self.resource_group, str(exc)))

def delete_vnet_connection(self):
try:
return self.web_client.web_apps.delete_swift_virtual_network(resource_group_name=self.resource_group, name=self.name)
except Exception as exc:
self.fail("Error deleting webapp vnet connection {0} (rg={1}) - {3}".format(self.name, self.resource_group, str(exc)))

def create_or_update_vnet_connection(self, vnet):
try:
return self.web_client.web_apps.create_or_update_swift_virtual_network_connection(
resource_group_name=self.resource_group, name=self.name, connection_envelope=vnet)
except Exception as exc:
self.fail("Error creating/updating webapp vnet connection {0} (vnet={1}, rg={2}) - {3}".format(
self.name, self.vnet_name, self.resource_group, str(exc)))

def get_subnet(self):
try:
return self.network_client.subnets.get(resource_group_name=self.vnet_resource_group, virtual_network_name=self.vnet_name, subnet_name=self.subnet)
except Exception as exc:
self.fail("Error getting subnet {0} in vnet={1} (rg={2}) - {3}".format(self.subnet, self.vnet_name, self.vnet_resource_group, str(exc)))

def set_results(self, vnet):
vnet_dict = vnet.as_dict()

output = dict()
output['id'] = vnet_dict['id']
output['name'] = vnet_dict['name']
subnet_id = vnet_dict.get('subnet_resource_id', vnet_dict.get('vnet_resource_id'))
output['vnet_resource_id'] = subnet_id
subnet_detail = self.get_subnet_detail(subnet_id)
output['vnet_resource_group'] = subnet_detail['resource_group']
output['vnet_name'] = subnet_detail['vnet_name']
output['subnet_name'] = subnet_detail['subnet_name']

return output


def main():
AzureRMWebAppVnetConnection()


if __name__ == '__main__':
main()
Loading