text: # --------------------------------------------------------------------------------------------
  # Copyright (c) Microsoft Corporation. All rights reserved.
  # Licensed under the MIT License. See License.txt in the project root for license information.
  # --------------------------------------------------------------------------------------------
  
  from knack.log import get_logger
  from knack.util import CLIError
  from azure.cli.core.commands import LongRunningOperation
  from azure.mgmt.web.models import IpSecurityRestriction
  from azure.mgmt.network.models import ServiceEndpointPropertiesFormat
  from azure.cli.command_modules.appservice.custom import get_site_configs
  from azure.cli.command_modules.appservice._appservice_utils import _generic_site_operation
  from azure.cli.command_modules.network._client_factory import network_client_factory
  
  logger = get_logger(__name__)
  
  
  def show_webapp_access_restrictions(cmd, resource_group_name, name, slot=None):
      import json
      configs = get_site_configs(cmd, resource_group_name, name, slot)
      access_restrictions = json.dumps(configs.ip_security_restrictions, default=lambda x: x.__dict__)
      scm_access_restrictions = json.dumps(configs.scm_ip_security_restrictions, default=lambda x: x.__dict__)
      access_rules = {
          "scmIpSecurityRestrictionsUseMain": configs.scm_ip_security_restrictions_use_main,
          "ipSecurityRestrictions": json.loads(access_restrictions),
          "scmIpSecurityRestrictions": json.loads(scm_access_restrictions)
      }
      return access_rules
  
  
  def add_webapp_access_restriction(
          cmd, resource_group_name, name, rule_name, priority,
          action='Allow', ip_address=None, subnet=None,
          vnet_name=None, description=None, scm_site=False,
          ignore_missing_vnet_service_endpoint=False, slot=None):
      configs = get_site_configs(cmd, resource_group_name, name, slot)
  
      # get rules list
      access_rules = configs.scm_ip_security_restrictions if scm_site else configs.ip_security_restrictions
      # check for null
      access_rules = access_rules or []
  
      rule_instance = None
      if subnet or vnet_name:
          subnet_id = _validate_subnet(cmd.cli_ctx, subnet, vnet_name, resource_group_name)
          if not ignore_missing_vnet_service_endpoint:
              _ensure_subnet_service_endpoint(cmd.cli_ctx, subnet_id)
  
          for rule in list(access_rules):
              if rule.vnet_subnet_resource_id:
                  if rule.action.lower() == action.lower() and rule.vnet_subnet_resource_id.lower() == subnet_id.lower():
                      rule_instance = rule
                      break
  
          if rule_instance:
              rule_instance.name = rule_name
              rule_instance.priority = priority
              rule_instance.description = description if description else rule_instance.description
          else:
              rule_instance = IpSecurityRestriction(
                  name=rule_name, vnet_subnet_resource_id=subnet_id,
                  priority=priority, action=action, tag='Default', description=description)
              access_rules.append(rule_instance)
  
      if ip_address:
          for rule in list(access_rules):
              if rule.ip_address:
                  if rule.action.lower() == action.lower() and rule.ip_address.lower() == ip_address.lower():
                      rule_instance = rule
                      break
  
          if rule_instance:
              rule_instance.name = rule_name
              rule_instance.priority = priority
              rule_instance.description = description or rule_instance.description
          else:
              rule_instance = IpSecurityRestriction(
                  name=rule_name, ip_address=ip_address,
                  priority=priority, action=action, tag='Default', description=description)
              access_rules.append(rule_instance)
  
      result = _generic_site_operation(
          cmd.cli_ctx, resource_group_name, name, 'update_configuration', slot, configs)
      return result.scm_ip_security_restrictions if scm_site else result.ip_security_restrictions
  
  
  def remove_webapp_access_restriction(cmd, resource_group_name, name, rule_name, scm_site=False, slot=None):
      configs = get_site_configs(cmd, resource_group_name, name, slot)
      rule_instance = None
      # get rules list
      access_rules = configs.scm_ip_security_restrictions if scm_site else configs.ip_security_restrictions
  
      for rule in list(access_rules):
          if rule.name.lower() == rule_name.lower():
              rule_instance = rule
              break
  
      if rule_instance is not None:
          access_rules.remove(rule_instance)
  
      result = _generic_site_operation(
          cmd.cli_ctx, resource_group_name, name, 'update_configuration', slot, configs)
      return result.scm_ip_security_restrictions if scm_site else result.ip_security_restrictions
  
  
  def set_webapp_access_restriction(cmd, resource_group_name, name, use_same_restrictions_for_scm_site, slot=None):
      configs = get_site_configs(cmd, resource_group_name, name, slot)
      setattr(configs, 'scm_ip_security_restrictions_use_main', bool(use_same_restrictions_for_scm_site))
  
      use_main = _generic_site_operation(
          cmd.cli_ctx, resource_group_name, name, 'update_configuration',
          slot, configs).scm_ip_security_restrictions_use_main
      use_main_json = {
          "scmIpSecurityRestrictionsUseMain": use_main
      }
      return use_main_json
  
  
  def _validate_subnet(cli_ctx, subnet, vnet_name, resource_group_name):
      from msrestazure.tools import is_valid_resource_id
      subnet_is_id = is_valid_resource_id(subnet)
  
      if subnet_is_id and not vnet_name:
          return subnet
      if subnet and not subnet_is_id and vnet_name:
          from msrestazure.tools import resource_id
          from azure.cli.core.commands.client_factory import get_subscription_id
          return resource_id(
              subscription=get_subscription_id(cli_ctx),
              resource_group=resource_group_name,
              namespace='Microsoft.Network',
              type='virtualNetworks',
              name=vnet_name,
              child_type_1='subnets',
              child_name_1=subnet)
      raise CLIError('Usage error: --subnet ID | --subnet NAME --vnet-name NAME')
  
  
  def _ensure_subnet_service_endpoint(cli_ctx, subnet_id):
      from msrestazure.tools import parse_resource_id
      subnet_id_parts = parse_resource_id(subnet_id)
      subnet_resource_group = subnet_id_parts['resource_group']
      subnet_vnet_name = subnet_id_parts['name']
      subnet_name = subnet_id_parts['resource_name']
  
      vnet_client = network_client_factory(cli_ctx)
      subnet_obj = vnet_client.subnets.get(subnet_resource_group, subnet_vnet_name, subnet_name)
      subnet_obj.service_endpoints = subnet_obj.service_endpoints or []
      service_endpoint_exists = False
      for s in subnet_obj.service_endpoints:
          if s.service == "Microsoft.Web":
              service_endpoint_exists = True
              break
  
      if not service_endpoint_exists:
          web_service_endpoint = ServiceEndpointPropertiesFormat(service="Microsoft.Web")
          subnet_obj.service_endpoints.append(web_service_endpoint)
          poller = vnet_client.subnets.create_or_update(
              subnet_resource_group, subnet_vnet_name,
              subnet_name, subnet_parameters=subnet_obj)
          # Ensure subnet is updated to avoid update conflict
          LongRunningOperation(cli_ctx)(poller)
  