# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
# pylint: disable=line-too-long
# pylint: disable=too-many-lines
import os
import unittest
import tempfile

from azure.cli.testsdk.constants import AUX_SUBSCRIPTION
from azure.cli.testsdk.scenario_tests import AllowLargeResponse
from azure.cli.core.commands.client_factory import get_subscription_id
from azure.core.exceptions import HttpResponseError
from .recording_processors import StorageAccountSASReplacer

from azure.cli.testsdk import (
    ScenarioTest, LiveScenarioTest, LocalContextScenarioTest, ResourceGroupPreparer, StorageAccountPreparer, live_only,
    KeyVaultPreparer, record_only)

from knack.util import CLIError

from azure.mgmt.core.tools import resource_id

from .credential_replacer import ExpressRoutePortLOAContentReplacer

TEST_DIR = os.path.abspath(os.path.join(os.path.abspath(__file__), '..'))
CERTS_DIR = os.path.join(TEST_DIR, 'certs')


class NetworkApplicationSecurityGroupScenario(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_network_asg')
    def test_network_asg(self, resource_group):

        self.kwargs.update({
            'asg': 'asg1'
        })

        count1 = len(self.cmd('network asg list').get_output_in_json())
        self.cmd('network asg create -g {rg} -n {asg} --tags foo=doo',
                 checks=self.check('tags.foo', 'doo'))
        self.cmd('network asg update -g {rg} -n {asg} --tags foo=bar',
                 checks=self.check('tags.foo', 'bar'))
        count2 = len(self.cmd('network asg list').get_output_in_json())
        self.assertTrue(count2 == count1 + 1)
        self.cmd('network asg show -g {rg} -n {asg}', checks=[
            self.check('name', '{asg}'),
            self.check('resourceGroup', '{rg}'),
            self.check('tags.foo', 'bar')
        ])
        self.cmd('network asg delete -g {rg} -n {asg}')
        count3 = len(self.cmd('network asg list').get_output_in_json())
        self.assertTrue(count3 == count1)


class NetworkLoadBalancerWithSku(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_network_lb_sku')
    def test_network_lb_sku(self, resource_group):

        self.kwargs.update({
            'lb': 'lb1',
            'sku': 'standard',
            'location': 'eastus2',
            'ip': 'pubip1'
        })

        self.cmd('network lb create -g {rg} -l {location} -n {lb} --sku {sku} --public-ip-address {ip}')
        self.cmd('network lb show -g {rg} -n {lb}', checks=[
            self.check('sku.name', 'Standard')
        ])

        # test network lb update command
        self.cmd('network lb update -g {rg} -n {lb} --set tags.label=1544 --force-string')
        self.cmd('network lb update -g {rg} -n {lb} --tags CostCenter=MyTestGroup')
        self.cmd('network lb show -g {rg} -n {lb}', checks=[
            self.check('tags.CostCenter', 'MyTestGroup')
        ])

        self.cmd('network public-ip show -g {rg} -n {ip}', checks=[
            self.check('sku.name', 'Standard'),
            self.check('publicIPAllocationMethod', 'Static')
        ])


class NetworkPrivateEndpoints(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_network_private_endpoints')
    def test_network_private_endpoints(self, resource_group):

        self.kwargs.update({
            'lb': 'lb1',
            'sku': 'Standard',
            'vnet': 'vnet1',
            'subnet1': 'subnet1',
            'subnet2': 'subnet2',
            'location': 'centralus',
            'ip': 'pubip1',
            'lks1': 'lks1',
            'lks2': 'lks2',
            'pe': 'pe1',
            'rg': resource_group,
            'nic': 'nic1',
        })

        # Create PLS
        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name {subnet1} -l {location}')
        self.cmd('network lb create -g {rg} -l {location} -n {lb} --public-ip-address {ip} --sku {sku}')
        self.cmd('network vnet subnet update -g {rg} -n {subnet1} --vnet-name {vnet} --disable-private-link-service-network-policies')
        self.cmd('network vnet subnet create -g {rg} -n {subnet2} --vnet-name {vnet} --address-prefixes 10.0.2.0/24 --default-outbound false')
        self.cmd('network vnet subnet update -g {rg} -n {subnet2} --vnet-name {vnet} --disable-private-endpoint-network-policies')
        pls1 = self.cmd('network private-link-service create -g {rg} -n {lks1} --vnet-name {vnet} --subnet {subnet1} --lb-name {lb} --lb-frontend-ip-configs LoadBalancerFrontEnd -l {location}', checks=[
            self.check('type', 'Microsoft.Network/privateLinkServices'),
            self.check('provisioningState', 'Succeeded'),
            self.check('name', self.kwargs['lks1'])
        ]).get_output_in_json()
        self.kwargs['pls_id'] = pls1['id']
        self.cmd('network private-endpoint list-types -l {location}')

        self.cmd('network private-endpoint create -g {rg} -n {pe} --vnet-name {vnet} --subnet {subnet2} --private-connection-resource-id {pls_id} --connection-name tttt -l {location} --nic-name {nic}', checks=[
            self.check('name', 'pe1'),
            self.check('provisioningState', 'Succeeded'),
            self.check('customNetworkInterfaceName', self.kwargs['nic']),
        ])

        # temporarily disable the test
        '''
        self.cmd('network private-endpoint update -g {rg} -n {pe} --request-message "test"', checks=[
            self.check('privateLinkServiceConnections[0].requestMessage', 'test')
        ])
        '''

        self.cmd('network private-endpoint list')
        self.cmd('network private-endpoint list -g {rg}', checks=[
            self.check('length(@)', 1)
        ])

        pe_connection_name = self.cmd('network private-link-service show -g {rg} -n {lks1}').get_output_in_json()['privateEndpointConnections'][0]['name']
        self.kwargs['pe_connect'] = pe_connection_name
        self.cmd('network private-link-service connection update -g {rg} -n {pe_connect} --service-name {lks1} --connection-status Rejected --action-required "need action"')
        self.cmd('network private-endpoint show -g {rg} -n {pe}', checks=[
            self.check('privateLinkServiceConnections[0].privateLinkServiceConnectionState.status', 'Rejected'),
            self.check('privateLinkServiceConnections[0].privateLinkServiceConnectionState.actionsRequired', "need action")
        ])
        self.cmd('network private-link-service connection delete -g {rg} -n {pe_connect} --service-name {lks1}')
        self.cmd('network private-link-service show -g {rg} -n {lks1}', checks=[
            self.check('length(privateEndpointConnections)', 0)
        ])
        self.cmd('network private-endpoint delete -g {rg} -n {pe}')

    @ResourceGroupPreparer(name_prefix="cli_test_network_private_endpoint_", location="eastus")
    @StorageAccountPreparer(name_prefix="ipconfig", kind="StorageV2")
    def test_network_private_endpoint_ip_config(self, storage_account):
        self.kwargs.update({
            "sa": storage_account,
            "loc": "eastus",
            "vnet": self.create_random_name("vnet-", 24),
            "subnet": self.create_random_name("subnet-", 24),
            "pe": self.create_random_name("pe-", 24),
            "connection": self.create_random_name("connection-", 24),
            "ipconfig1": "ipconfig1",
            "ipconfig2": "ipconfig2",
        })

        # prepare network
        self.cmd("network vnet create -n {vnet} -l {loc} -g {rg} --address-prefixes 10.0.0.0/16 --subnet-name {subnet} --subnet-prefixes 10.0.0.0/24")
        self.cmd("network vnet subnet update -n {subnet} -g {rg} --vnet-name {vnet} --disable-private-endpoint-network-policies true")

        # create private endpoint connection
        pl_resources = self.cmd("storage account private-link-resource list --account-name {sa} -g {rg}").get_output_in_json()
        self.kwargs["group_id"] = pl_resources[0]["groupId"]
        self.kwargs["sa_id"] = self.cmd('storage account show -n {sa} -g {rg}').get_output_in_json()["id"]
        self.cmd(
            "network private-endpoint create -n {pe} -g {rg} --vnet-name {vnet} --subnet {subnet} --connection-name {connection} --group-id {group_id} --private-connection-resource-id {sa_id} "
            "--ip-config name={ipconfig1} group-id={group_id} member-name=blob private-ip-address=10.0.0.4 "
            "--ip-config name={ipconfig2} private-ip-address=10.0.0.6",
            checks=[
                self.check("length(ipConfigurations)", 2),
                self.check("ipConfigurations[0].name", self.kwargs["ipconfig1"]),
                self.check("ipConfigurations[1].name", self.kwargs["ipconfig2"]),
            ]
        )

        # check ip configuration operations
        self.cmd("network private-endpoint ip-config remove -n {ipconfig2} -g {rg} --endpoint-name {pe}")
        self.cmd(
            "network private-endpoint ip-config add -n {ipconfig2} -g {rg} --endpoint-name {pe} --group-id {group_id} --member-name blob2 --private-ip-address 10.0.0.6",
            checks=[
                self.check("length(ipConfigurations)", 2),
                self.check("ipConfigurations[1].name", self.kwargs["ipconfig2"]),
            ]
        )
        self.cmd(
            "network private-endpoint ip-config list -g {rg} --endpoint-name {pe}",
            checks=[
                self.check("length(@)", 2),
                self.check("@[0].name", self.kwargs["ipconfig1"]),
                self.check("@[1].name", self.kwargs["ipconfig2"]),
            ]
        )

        self.cmd("network private-endpoint delete -n {pe} -g {rg}")
        self.cmd("network private-endpoint list -g {rg}", checks=[self.check("length(@)", 0)])

        # create private endpoint connection with --ip-configs
        self.cmd(
            "network private-endpoint create -n {pe} -g {rg} --vnet-name {vnet} --subnet {subnet} --connection-name {connection} --group-id {group_id} --private-connection-resource-id {sa_id} "
            "--ip-configs [{{name:{ipconfig1},group-id:{group_id},member-name:blob,private-ip-address:10.0.0.4}},{{name:{ipconfig2},private-ip-address:10.0.0.6}}]",
            checks=[
                self.check("length(ipConfigurations)", 2),
                self.check("ipConfigurations[0].name", self.kwargs["ipconfig1"]),
                self.check("ipConfigurations[1].name", self.kwargs["ipconfig2"]),
            ]
        )

    @ResourceGroupPreparer(name_prefix="cli_test_network_private_endpoint_", location="eastus")
    @StorageAccountPreparer(name_prefix="asg", kind="StorageV2")
    def test_network_private_endpoint_asg(self, storage_account):
        self.kwargs.update({
            "sa": storage_account,
            "loc": "eastus",
            "vnet": self.create_random_name("vnet-", 24),
            "subnet": self.create_random_name("subnet-", 24),
            "pe": self.create_random_name("pe-", 24),
            "connection": self.create_random_name("connection-", 24),
            "asg1": "asg1",
            "asg2": "asg2",
        })

        # prepare network
        self.cmd("network vnet create -n {vnet} -l {loc} -g {rg} --address-prefixes 10.0.0.0/16 --subnet-name {subnet} --subnet-prefixes 10.0.0.0/24")
        self.cmd("network vnet subnet update -n {subnet} -g {rg} --vnet-name {vnet} --disable-private-endpoint-network-policies true")

        # create private endpoint connection
        pl_resources = self.cmd("storage account private-link-resource list --account-name {sa} -g {rg}").get_output_in_json()
        self.kwargs["group_id"] = pl_resources[0]["groupId"]
        self.kwargs["sa_id"] = self.cmd('storage account show -n {sa} -g {rg}').get_output_in_json()["id"]
        self.kwargs["id1"] = self.cmd("network asg create -n {asg1} -g {rg}").get_output_in_json()["id"]
        self.kwargs["id2"] = self.cmd("network asg create -n {asg2} -g {rg}").get_output_in_json()["id"]
        self.cmd(
            "network private-endpoint create -n {pe} -g {rg} --vnet-name {vnet} --subnet {subnet} --connection-name {connection} --group-id {group_id} --private-connection-resource-id {sa_id} "
            "--asg id={id1} "
            "--asg id={id2}",
            checks=[
                self.check("length(applicationSecurityGroups)", 2),
                self.check("applicationSecurityGroups[0].id", self.kwargs["id1"]),
                self.check("applicationSecurityGroups[1].id", self.kwargs["id2"]),
            ]
        )

        # check application security group operations
        self.cmd("network private-endpoint asg remove -g {rg} --endpoint-name {pe} --asg-id {id2}")
        self.cmd(
            "network private-endpoint asg add -g {rg} --endpoint-name {pe} --asg-id {id2}",
            checks=[
                self.check("length(applicationSecurityGroups)", 2),
                self.check("applicationSecurityGroups[1].id", self.kwargs["id2"]),
            ]
        )
        self.cmd(
            "network private-endpoint asg list -g {rg} --endpoint-name {pe}",
            checks=[
                self.check("length(@)", 2),
                self.check("@[0].id", self.kwargs["id1"]),
                self.check("@[1].id", self.kwargs["id2"]),
            ]
        )

        self.cmd("network private-endpoint delete -n {pe} -g {rg}")
        self.cmd("network private-endpoint list -g {rg}", checks=[self.check("length(@)", 0)])

        # create private endpoint connection with --asgs
        self.cmd(
            "network private-endpoint create -n {pe} -g {rg} --vnet-name {vnet} --subnet {subnet} --connection-name {connection} --group-id {group_id} --private-connection-resource-id {sa_id} "
            "--asgs [{{id:{id1}}},{{id:{id2}}}]",
            checks=[
                self.check("length(applicationSecurityGroups)", 2),
                self.check("applicationSecurityGroups[0].id", self.kwargs["id1"]),
                self.check("applicationSecurityGroups[1].id", self.kwargs["id2"]),
            ]
        )

    @ResourceGroupPreparer(name_prefix='fanqiu_cli_test_network_private_endpoints', location='CentralUSEuap')
    @StorageAccountPreparer(name_prefix='saplr', kind='StorageV2')
    def test_network_private_endpoint_private_dns_zone_group(self, resource_group, storage_account):
        self.kwargs.update({
            'sa': storage_account,
            'loc': 'CentralUSEuap',
            'vnet': self.create_random_name('cli-vnet-', 24),
            'subnet': self.create_random_name('cli-subnet-', 24),
            'pe': self.create_random_name('cli-pe-', 24),
            'pe_connection': self.create_random_name('cli-pec-', 24),
            'zone_name1': 'www.clizone1.com',
            'zone_name2': 'www.clizone2.com',
            'private_dns_zone_group_name': 'clidnsgroup',
            'private_zone_name1': 'clizone1',
            'private_zone_name2': 'clizone2'
        })

        # Prepare network
        self.cmd('network vnet create -n {vnet} -g {rg} -l {loc} --subnet-name {subnet}',
                 checks=self.check('length(newVNet.subnets)', 1))
        self.cmd('network vnet subnet update -n {subnet} --vnet-name {vnet} -g {rg} '
                 '--disable-private-endpoint-network-policies true',
                 checks=self.check('privateEndpointNetworkPolicies', 'Disabled'))

        # Create a private endpoint connection
        pr = self.cmd('storage account private-link-resource list --account-name {sa} -g {rg}').get_output_in_json()
        self.kwargs['group_id'] = pr[0]['groupId']

        storage = self.cmd('storage account show -n {sa} -g {rg}').get_output_in_json()
        self.kwargs['sa_id'] = storage['id']
        private_endpoint = self.cmd(
            'network private-endpoint create -g {rg} -n {pe} --vnet-name {vnet} --subnet {subnet} -l {loc} '
            '--connection-name {pe_connection} --private-connection-resource-id {sa_id} '
            '--group-ids blob').get_output_in_json()
        self.assertEqual(private_endpoint['name'], self.kwargs['pe'])
        self.assertEqual(private_endpoint['privateLinkServiceConnections'][0]['name'], self.kwargs['pe_connection'])
        self.assertEqual(
            private_endpoint['privateLinkServiceConnections'][0]['privateLinkServiceConnectionState']['status'],
            'Approved')
        self.assertEqual(private_endpoint['privateLinkServiceConnections'][0]['provisioningState'], 'Succeeded')
        self.assertEqual(private_endpoint['privateLinkServiceConnections'][0]['groupIds'][0], self.kwargs['group_id'])
        self.kwargs['pe_id'] = private_endpoint['privateLinkServiceConnections'][0]['id']

        # Show the connection at storage account
        storage = self.cmd('storage account show -n {sa} -g {rg}').get_output_in_json()
        self.assertIn('privateEndpointConnections', storage)
        self.assertEqual(len(storage['privateEndpointConnections']), 1)
        self.assertEqual(storage['privateEndpointConnections'][0]['privateLinkServiceConnectionState']['status'],
                         'Approved')

        self.kwargs['sa_pec_id'] = storage['privateEndpointConnections'][0]['id']
        self.kwargs['sa_pec_name'] = storage['privateEndpointConnections'][0]['name']

        self.cmd('storage account private-endpoint-connection show --account-name {sa} -g {rg} --name {sa_pec_name}',
                 checks=self.check('id', '{sa_pec_id}'))

        self.cmd('network private-endpoint show -g {rg} -n {pe}', checks=[
            self.check('length(customDnsConfigs)', 1)
        ])
        self.cmd('network private-dns zone create -n {zone_name1} -g {rg}')
        self.cmd('network private-dns zone create -n {zone_name2} -g {rg}')

        self.cmd('network private-endpoint dns-zone-group create --endpoint-name {pe} -g {rg} -n {private_dns_zone_group_name} '
                 '--zone-name {private_zone_name1} --private-dns-zone {zone_name1}',
                 checks=[
                     self.check('name', '{private_dns_zone_group_name}')
                 ])

        self.cmd('network private-endpoint dns-zone-group add --endpoint-name {pe} -g {rg} -n {private_dns_zone_group_name} '
                 '--zone-name {private_zone_name2} --private-dns-zone {zone_name2}',
                 checks=[
                     self.check('length(privateDnsZoneConfigs)', 2)
                 ])

        self.cmd('network private-endpoint dns-zone-group show --endpoint-name {pe} -g {rg} -n {private_dns_zone_group_name}', checks=[
            self.check('length(privateDnsZoneConfigs)', 2)
        ])
        self.cmd('network private-endpoint dns-zone-group list --endpoint-name {pe} -g {rg}', checks=[
            self.check('length(@)', 1)
        ])
        self.cmd('network private-endpoint dns-zone-group remove --endpoint-name {pe} -g {rg} -n {private_dns_zone_group_name} '
                 '--zone-name {private_zone_name2}')
        self.cmd('network private-endpoint dns-zone-group show --endpoint-name {pe} -g {rg} -n {private_dns_zone_group_name}', checks=[
            self.check('length(privateDnsZoneConfigs)', 1)
        ])
        self.cmd('network private-endpoint dns-zone-group delete --endpoint-name {pe} -g {rg} -n {private_dns_zone_group_name}')


class NetworkPrivateLinkService(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_pls_udr')
    @AllowLargeResponse()
    def test_network_private_link_service_udr(self, resource_group):

        self.kwargs.update({
            'sku': 'Standard',
            'vnet': 'vnet1',
            'vnet_prefix': '10.0.0.0/16',
            'subnet1': 'subnet1',
            'subnet_prefix': '10.0.0.0/24',
            'location': 'westcentralus',
            'lks1': 'lks1',
            'destination_ip': '10.0.0.10'
        })

        self.cmd('network vnet create -g {rg} -n {vnet} --address-prefixes {vnet_prefix} --subnet-name {subnet1} --subnet-prefixes {subnet_prefix} -l {location}')
        self.cmd('az network vnet subnet update -n {subnet1} --vnet-name {vnet} -g {rg} --pls-network-policies disabled')
        self.cmd('network private-link-service create -n {lks1} -g {rg} --vnet-name {vnet} --subnet {subnet1} --destination-ip-address {destination_ip} -l {location}', checks=[
            self.check('type', 'Microsoft.Network/privateLinkServices'),
            self.check('enableProxyProtocol', False),
            self.check('destinationIPAddress', '{destination_ip}')
        ])

    @ResourceGroupPreparer(name_prefix='cli_test_network_private_link_service')
    @AllowLargeResponse()
    def test_network_private_link_service(self, resource_group):

        self.kwargs.update({
            'lb': 'lb1',
            'sku': 'Standard',
            'vnet': 'vnet1',
            'subnet1': 'subnet1',
            'subnet2': 'subnet2',
            'location': 'westcentralus',
            'ip': 'pubip1',
            'lks1': 'lks1',
            'lks2': 'lks2',
            'sub1': '00000000-0000-0000-0000-000000000000',
            'destination_ip': '10.0.0.1'
        })

        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name {subnet1} -l {location}')
        self.cmd('network lb create -g {rg} -l {location} -n {lb} --public-ip-address {ip} --sku {sku}')
        self.cmd('network vnet subnet update -g {rg} -n {subnet1} --vnet-name {vnet} --disable-private-link-service-network-policies')
        self.cmd('network vnet subnet create -g {rg} -n {subnet2} --vnet-name {vnet} --address-prefixes 10.0.2.0/24 --default-outbound false')
        self.cmd('network vnet subnet update -g {rg} -n {subnet2} --vnet-name {vnet} --disable-private-endpoint-network-policies')

        with self.assertRaises(HttpResponseError, msg=' either one LoadBalancerFrontendIpConfiguration if PLS with LB based scenario or DestinationIPAddress if PLS UDR and NSG scenario'):
            self.cmd('network private-link-service create -g {rg} -n {lks1} --vnet-name {vnet} --subnet {subnet1} --lb-name {lb} --lb-frontend-ip-configs LoadBalancerFrontEnd -l {location} --destination-ip-address {destination_ip}')
        self.cmd('network private-link-service create -g {rg} -n {lks1} --vnet-name {vnet} --subnet {subnet1} --lb-name {lb} --lb-frontend-ip-configs LoadBalancerFrontEnd -l {location}  --enable-proxy-protocol', checks=[
            self.check('type', 'Microsoft.Network/privateLinkServices'),
            self.check('length(ipConfigurations)', 1),
            self.check('length(loadBalancerFrontendIpConfigurations)', 1),
            self.check('enableProxyProtocol', True)
        ])

        self.cmd('network private-link-service update -g {rg} -n {lks1} --visibility {sub1} {sub1} --auto-approval {sub1} {sub1} --enable-proxy-protocol False --lb-name {lb} --lb-frontend-ip-configs LoadBalancerFrontEnd', checks=[
            self.check('length(visibility.subscriptions)', 2),
            self.check('length(autoApproval.subscriptions)', 2),
            self.check('enableProxyProtocol', False)
        ])
        self.cmd('network private-link-service list -g {rg}', checks=[
            self.check('length(@)', 1),
            self.check('@[0].type', 'Microsoft.Network/privateLinkServices')
        ])
        self.cmd('network private-link-service show -g {rg} -n {lks1}', checks=[
            self.check('type', 'Microsoft.Network/privateLinkServices'),
            self.check('length(ipConfigurations)', 1),
            self.check('length(loadBalancerFrontendIpConfigurations)', 1)
        ])
        self.cmd('network private-link-service list-auto-approved -l westus', self.check('type(@)', 'array'))
        self.cmd('network private-link-service delete -g {rg} -n {lks1}')

        self.cmd('network vnet subnet update -g {rg} -n {subnet1} --vnet-name {vnet} --disable-private-link-service-network-policies false', checks=[
            self.check('privateLinkServiceNetworkPolicies', 'Enabled')
        ])


class NetworkLoadBalancerWithZone(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_network_lb_zone')
    def test_network_lb_zone(self, resource_group):

        self.kwargs.update({
            'lb': 'lb1',
            'lb2': 'lb4',
            'lb3': 'lb5',
            'zone': '2',
            'location': 'eastus2',
            'ip': 'pubip1',
            'ip2': 'pubip2'
        })

        # LB with public ip
        self.cmd('network lb create -g {rg} -l {location} -n {lb} --public-ip-zone {zone} --public-ip-address {ip} --sku Standard')
        # No zone on LB and its front-ip-config
        self.cmd('network lb show -g {rg} -n {lb}', checks=[
            self.check("frontendIPConfigurations[0].zones", None),
            self.check("zones", None)
        ])
        # Zone on public-ip which LB uses to infer the zone
        self.cmd('network public-ip show -g {rg} -n {ip}', checks=[
            self.check('zones[0]', self.kwargs['zone'])
        ])

        # LB w/o public ip, so called ILB
        self.kwargs['lb'] = 'lb2'
        self.cmd('network lb create -g {rg} -l {location} -n {lb} --frontend-ip-zone {zone} --public-ip-address "" --vnet-name vnet1 --subnet subnet1 --sku Standard')
        # Zone on front-ip-config, and still no zone on LB resource
        self.cmd('network lb show -g {rg} -n {lb}', checks=[
            self.check("frontendIPConfigurations[0].zones[0]", self.kwargs['zone']),
            self.check("zones", None)
        ])
        # add a second frontend ip configuration
        self.cmd('network lb frontend-ip create -g {rg} --lb-name {lb} -n LoadBalancerFrontEnd2 -z {zone}  --vnet-name vnet1 --subnet subnet1', checks=[
            self.check("zones", [self.kwargs['zone']])
        ])

        # test for private-ip-address-version
        self.cmd('network lb create -g {rg} -n {lb2} -l westcentralus --sku Standard')
        self.cmd('network public-ip create -n {ip2} -g {rg} -l westcentralus --sku Standard --allocation-method Static --version IPv6 --ip-tags FirstPartyUsage=/NonProd')
        self.cmd('network lb frontend-ip create --lb-name {lb2} -n ipv6 -g {rg} --private-ip-address-version IPv6 --public-ip-address {ip2}', checks=[
            self.check('name', 'ipv6'),
            self.check('provisioningState', 'Succeeded')
        ])

    @ResourceGroupPreparer(name_prefix='test_network_lb_frontend_ip_zone', location='eastus2')
    def test_network_lb_frontend_ip_zone(self, resource_group):
        self.kwargs.update({
            'location': 'eastus2',
            'lb1': self.create_random_name('lb', 10),
            'lb2': self.create_random_name('lb', 10),
            'vnet1': self.create_random_name('vnet', 10),
            'vnet2': self.create_random_name('vnet', 10),
            'pool': self.create_random_name('poll', 10)
        })

        # LB with subnet : internal LB
        self.cmd('network lb create -g {rg} -l {location} -n {lb1} --vnet-name {vnet1} --subnet subnet --sku Standard')
        self.cmd('network lb frontend-ip create -g {rg} --lb-name {lb1} -n LoadBalancerFrontEnd2 -z 1 2 3 --vnet-name {vnet1} --subnet subnet', checks=[
            self.check("length(zones)", 3)
        ])
        self.cmd('network lb create -g {rg} -n {lb2} --sku standard --vnet-name {vnet2} --subnet default --frontend-ip-zone 1 2 3 --backend-pool-name {pool}', checks=[
            self.check("loadBalancer.frontendIPConfigurations[0].zones", ['1', '2', '3'])
        ])


class NetworkPublicIpWithSku(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_network_lb_sku')
    def test_network_public_ip_sku(self, resource_group):

        self.kwargs.update({
            'standard_sku': 'Standard',
            'basic_sku': 'Basic',
            'regional_tier': 'Regional',
            'global_tier': 'Global',
            'location': 'eastus2',
            'ip1': 'pubip1',
            'ip2': 'pubip2',
            'ip3': 'pubip3',
            'ip4': 'pubip4'
        })

        self.cmd('network public-ip create -g {rg} -l {location} -n {ip1} --ip-tags FirstPartyUsage=/NonProd')
        self.cmd('network public-ip show -g {rg} -n {ip1}', checks=[
            self.check('sku.name', self.kwargs.get('standard_sku')),
            self.check('sku.tier', self.kwargs.get('regional_tier')),
            self.check('publicIPAllocationMethod', 'Static')
        ])

        self.cmd('network public-ip create -g {rg} -l {location} -n {ip2} --sku {standard_sku} --tags foo=doo --ip-tags FirstPartyUsage=/NonProd')
        self.cmd('network public-ip show -g {rg} -n {ip2}', checks=[
            self.check('sku.name', self.kwargs.get('standard_sku')),
            self.check('sku.tier', self.kwargs.get('regional_tier')),
            self.check('publicIPAllocationMethod', 'Static'),
            self.check('tags.foo', 'doo')
        ])

        self.cmd('network public-ip create -g {rg} -l {location} -n {ip3} --sku {standard_sku} --tier {global_tier} --ip-tags FirstPartyUsage=/NonProd')
        self.cmd('network public-ip show -g {rg} -n {ip3}', checks=[
            self.check('sku.name', self.kwargs.get('standard_sku')),
            self.check('sku.tier', self.kwargs.get('global_tier')),
            self.check('publicIPAllocationMethod', 'Static')
        ])

        self.cmd('network public-ip create -g {rg} -n {ip4} --sku standardv2 --allocation-method static --ip-tags FirstPartyUsage=/NonProd', checks=[
            self.check('publicIp.sku.name', 'StandardV2'),
        ])


class NetworkCustomIPPrefix(ScenarioTest):
    @ResourceGroupPreparer(name_prefix="cli_test_network_custom_ip_prefix_", location="eastus2")
    def test_network_custom_ip_prefix_crud(self):
        self.kwargs.update({
            "cip_name1": self.create_random_name("cip-", 8),
            "cip_name2": self.create_random_name("cip-", 8),
        })
        self.cmd(
            "network custom-ip prefix create --name {cip_name1} --resource-group {rg} --cidr 2001:250:6000::/48 --is-parent",
            checks=[
                self.check("name", "{cip_name1}"),
                self.check("prefixType", "Parent")
            ]
        )
        self.cmd(
            "network custom-ip prefix create -n {cip_name2} -z 1 -g {rg} --cidr 0.0.0.0/24 "
            "--asn 65515 --geo GLOBAL --is-advertised false",
            checks=[
                self.check("name", "{cip_name2}"),
                self.check("asn", "65515"),
                self.check("geo", "GLOBAL"),
                self.check("expressRouteAdvertise", False)
            ]
        )
        self.cmd(
            "network custom-ip prefix list -g {rg}",
            checks=[
                self.check("length(@)", 2),
                self.check("@[0].name", "{cip_name1}")
            ]
        )
        self.cmd("network custom-ip prefix update -n {cip_name2} -g {rg} --tags foo=bar")
        self.cmd(
            "network custom-ip prefix show -n {cip_name2} -g {rg}",
            checks=[
                self.check("name", "{cip_name2}"),
                self.check("tags.foo", "bar")
            ]
        )


    @record_only()
    def test_network_custom_ip_prefix_update_state(self):
        self.kwargs.update({
            "rg": "cli_test_custom_ip_prefix",
            "cip_name": "prefix1"
        })

        self.cmd(
            "network custom-ip prefix update -n {cip_name} -g {rg} --state commission --no-internet-advertise false",
            checks=[
                self.check("commissionedState", "Commissioning"),
                self.check("noInternetAdvertise", False)
            ]
        )


class NetworkPublicIpPrefix(ScenarioTest):

    @record_only()  # cannot assign both tags and a public IP prefix to a public IP address in Azure
    @ResourceGroupPreparer(name_prefix='cli_test_network_public_ip_prefix', location='eastus2')
    def test_network_public_ip_prefix(self, resource_group):

        self.kwargs.update({
            'prefix': 'prefix1',
            'pip': 'pip1',
            'prefix_v6': self.create_random_name('public-ip-prefix-', 24),
            'pip_v6': self.create_random_name('public-ip-', 16)
        })

        # Test prefix CRUD
        self.cmd('network public-ip prefix create -g {rg} -n {prefix} --length 30',
                 checks=self.check('prefixLength', 30))
        self.cmd('network public-ip prefix update -g {rg} -n {prefix} --tags foo=doo')

        # test prefix show command
        self.cmd('network public-ip prefix show -g {rg} -n {prefix}',
                 checks=self.check('tags.foo', 'doo'))

        self.cmd('network public-ip prefix list -g {rg}',
                 checks=self.check('length(@)', 1))
        self.cmd('network public-ip prefix delete -g {rg} -n {prefix}')
        self.cmd('network public-ip prefix list -g {rg}',
                 checks=self.is_empty())

        # Test public IP create with prefix
        self.cmd('network public-ip prefix create -g {rg} -n {prefix} --length 30')
        self.cmd('network public-ip create -g {rg} -n {pip} --public-ip-prefix {prefix} --sku Standard',
                 checks=self.check("publicIp.publicIPPrefix.id.contains(@, '{prefix}')", True))
        self.cmd('network public-ip prefix create -n {prefix_v6} -g {rg} --version IPv6 --length 126 -z 1 3 2')
        self.cmd(
            'network public-ip create -n {pip_v6} -g {rg} --public-ip-prefix {prefix_v6}',
            checks=[
                self.check('publicIp.name', '{pip_v6}'),
                self.check('publicIp.publicIPAddressVersion', 'IPv6'),
                self.check('publicIp.zones', ['1', '3', '2'])
            ]
        )

        # Test IP address version
        self.kwargs.update({
            'prefix_name_ipv4': 'public_ip_prefix_0',
            'prefix_name_ipv5': 'public_ip_prefix_1',
            'prefix_name_ipv6': 'public_ip_prefix_2'
        })

        # Check the default ip address version value
        self.cmd('network public-ip prefix create -g {rg} -n {prefix_name_ipv4} --length 30', checks=[
            self.check('publicIPAddressVersion', 'IPv4')
        ])

        # Check the creation of public IP prefix with IPv6 address option
        # Note: prefix length for IPv6 is minimal 124 and maximal 127 respectively
        self.cmd('network public-ip prefix create -g {rg} -n {prefix_name_ipv6} --length 127 --version IPv6', checks=[
            self.check('publicIPAddressVersion', 'IPv6')
        ])

        # Check with unsupported IP address version: IPv5
        with self.assertRaisesRegex(SystemExit, '2'):
            self.cmd('network public-ip prefix create -g {rg} -n {prefix_name_ipv6} --length 127 --version IPv5')

    @ResourceGroupPreparer(name_prefix='cli_test_network_public_ip_prefix_zone', location='eastus2')
    def test_network_public_ip_prefix_zone(self, resource_group):
        self.kwargs.update({
            'prefix': 'prefix1',
        })

        # Test prefix with multi zones
        self.cmd('network public-ip prefix create -g {rg} -n {prefix} --length 30 --zone 1 2 3', checks=[
            self.check('prefixLength', 30),
            self.check('length(zones)', 3)
        ])

    @record_only()  # cannot assign both tags and a public IP prefix to a public IP address in Azure
    @ResourceGroupPreparer(name_prefix='cli_test_network_public_ip_prefix_with_ip_address', location='eastus2')
    def test_network_public_ip_prefix_with_ip_address(self, resource_group):
        self.kwargs.update({
            'prefix_name_ipv4': 'public_ip_prefix_0',
            'pip': 'pip1'
        })

        ip_prefix = self.cmd('network public-ip prefix create -g {rg} -n {prefix_name_ipv4} --length 28', checks=[
            self.check('publicIPAddressVersion', 'IPv4')
        ]).get_output_in_json()

        ip_address = ip_prefix['ipPrefix'][:-3]

        # Create public ip with ip address
        self.cmd('network public-ip create -g {rg} -n {pip} --public-ip-prefix {prefix_name_ipv4} --sku Standard --ip-address ' + ip_address,
                 checks=self.check("publicIp.publicIPPrefix.id.contains(@, '{prefix_name_ipv4}')", True))

    @live_only()
    @ResourceGroupPreparer(name_prefix="cli_test_network_public_ip_prefix_", location="eastus2", subscription=AUX_SUBSCRIPTION)
    def test_network_public_ip_prefix_with_aux_custom(self, resource_group):
        self.kwargs.update({
            "aux_rg": resource_group,
            "aux_subscription": AUX_SUBSCRIPTION,
            "public_prefix_name": self.create_random_name("public-prefix-", 20)
        })

        # previously created custom ip prefix
        self.kwargs["custom_id"] = self.cmd("network custom-ip prefix show -n ethan-cip -g ethan-rg").get_output_in_json()["id"]
        self.cmd(
            "network public-ip prefix create -n {public_prefix_name} -g {aux_rg} --length 31 --zone 2 3 1 "
            "--custom-ip-prefix-name {custom_id} --subscription {aux_subscription}",
            checks=[
                self.check("name", "{public_prefix_name}"),
                self.check("type", "Microsoft.Network/publicIPPrefixes")
            ]
        )

    @ResourceGroupPreparer(name_prefix='cli_test_network_public_ip_prefix_with_ip_tags', location='eastus2')
    def test_network_public_ip_prefix_with_ip_tags(self, resource_group):
        self.kwargs.update({
            'prefix': 'prefix1',
            'ip_tags': 'RoutingPreference=Internet'
        })
        # Test prefix create with param --ip-tags
        self.cmd('network public-ip prefix create -g {rg} -n {prefix} --length 30 --ip-tags {ip_tags}',
                 checks=[
                     self.check('ipTags[0].ipTagType', 'RoutingPreference'),
                     self.check('ipTags[0].tag', 'Internet')])


class NetworkMultiIdsShowScenarioTest(ScenarioTest):
    @live_only()
    @ResourceGroupPreparer(name_prefix='test_multi_id')
    def test_network_multi_id_show(self, resource_group):

        self.cmd('network public-ip create -g {rg} -n pip1 --ip-tags FirstPartyUsage=/NonProd')
        self.cmd('network public-ip create -g {rg} -n pip2 --ip-tags FirstPartyUsage=/NonProd')

        pip1 = self.cmd('network public-ip show -g {rg} -n pip1').get_output_in_json()
        pip2 = self.cmd('network public-ip show -g {rg} -n pip2').get_output_in_json()
        self.cmd('network public-ip show --ids {} {}'.format(pip1['id'], pip2['id']),
                 checks=self.check('length(@)', 2))


class NetworkUsageListScenarioTest(ScenarioTest):

    def test_network_usage_list(self):
        self.cmd('network list-usages --location westus', checks=self.check('type(@)', 'array'))


class NetworkAppGatewayDefaultScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_ag_basic')
    def test_network_app_gateway_with_defaults(self, resource_group):
        self.cmd('network vnet create -n vnet1 -g {rg} --address-prefix 10.0.0.0/16')
        self.cmd('network vnet subnet create -n subnet1 -g {rg} --vnet-name vnet1 --address-prefix 10.0.0.0/24 --default-outbound-access false')
        self.cmd('network public-ip create -g {rg} -n pubip1 --sku standard --ip-tags FirstPartyUsage=/NonProd')
        self.cmd('network application-gateway create -g {rg} -n ag1 --sku Standard_v2 --priority 1001 --vnet-name vnet1 --subnet subnet1 --public-ip-address pubip1 --enable-fips false')
        self.cmd('network application-gateway show --resource-group {rg} --name ag1', checks=self.check('enableFips', False))
        self.cmd('network application-gateway update -g {rg} -n ag1 --no-wait')
        self.cmd('network application-gateway update -g {rg} -n ag1 --no-wait '
                 '--capacity 3 --tags foo=doo --http2 Disabled --enable-fips true')
        self.cmd('network application-gateway wait -g {rg} -n ag1 --updated')

        ag_list = self.cmd('network application-gateway list --resource-group {rg}', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?resourceGroup == '{}']) == length(@)".format(resource_group), True)
        ]).get_output_in_json()
        ag_count = len(ag_list)

        self.cmd('network application-gateway show --resource-group {rg} --name ag1', checks=[
            self.check('type(@)', 'object'),
            self.check('name', 'ag1'),
            self.check('resourceGroup', resource_group),
            self.check('frontendIPConfigurations[0].privateIPAllocationMethod', 'Dynamic'),
            self.check("enableHttp2", False),
            self.check("enableFips", True),
            self.check("contains(defaultPredefinedSslPolicy, 'AppGwSslPolicy')", True),
        ])
        self.cmd('network application-gateway show-backend-health -g {rg} -n ag1')

        self.cmd('network application-gateway stop --resource-group {rg} -n ag1')
        self.cmd('network application-gateway start --resource-group {rg} -n ag1 --no-wait')
        self.cmd('network application-gateway delete --resource-group {rg} -n ag1')
        self.cmd('network application-gateway list --resource-group {rg}', checks=self.check('length(@)', ag_count - 1))

    @ResourceGroupPreparer(name_prefix='cli_test_ag_basic_with_waf_v2_sku')
    def test_network_app_gateway_with_waf_v2_sku(self, resource_group):
        self.cmd('network public-ip create -g {rg} -n pubip1 --sku Standard --ip-tags FirstPartyUsage=/NonProd')
        self.cmd('network application-gateway waf-policy create -n waf1 -g {rg}')
        self.cmd('network application-gateway create -g {rg} -n ag1 --sku WAF_v2 --public-ip-address pubip1 --waf-policy waf1 --priority 1001')

        self.cmd('network application-gateway list --resource-group {rg}', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?resourceGroup == '{}']) == length(@)".format(resource_group), True)
        ])

        self.cmd('network application-gateway show --resource-group {rg} --name ag1', checks=[
            self.check('type(@)', 'object'),
            self.check('name', 'ag1'),
            self.check('resourceGroup', resource_group),
            self.check('frontendIPConfigurations[0].privateIPAllocationMethod', 'Dynamic')
        ])
        self.cmd('network application-gateway show-backend-health -g {rg} -n ag1 '
                 '--host-name-from-http-settings --path /test --timeout 100 '
                 '--http-settings appGatewayBackendHttpSettings --address-pool appGatewayBackendPool')

    @ResourceGroupPreparer(name_prefix="cli_test_ag_with_non_v2_sku_", location="westus")
    def test_ag_with_non_v2_sku(self):
        self.kwargs.update({
            "ag_name": self.create_random_name("ag-", 12),
            "port_name": self.create_random_name("port-", 12),
            "lisener_name": self.create_random_name("lisener-", 12),
            "rule_name": self.create_random_name("rule-", 12),
        })

        self.cmd("network application-gateway create -n {ag_name} -g {rg} --sku WAF_Medium")

        self.kwargs["front_ip"] = self.cmd("network application-gateway show -n {ag_name} -g {rg}").get_output_in_json()["frontendIPConfigurations"][0]["name"]
        self.cmd("network application-gateway frontend-port create -n {port_name} -g {rg} --gateway-name {ag_name} --port 8080")
        self.cmd("network application-gateway http-listener create -n {lisener_name} -g {rg} --gateway-name {ag_name} --frontend-ip {front_ip} --frontend-port {port_name}")

        self.cmd(
            "network application-gateway rule create -n {rule_name} -g {rg} --gateway-name {ag_name} --http-listener {lisener_name}",
            checks=[
                self.check("name", "{ag_name}"),
                self.check("sku.tier", "WAF")
            ]
        )

        self.cmd("network application-gateway delete -n {ag_name} -g {rg}")

    @ResourceGroupPreparer(name_prefix='test_network_appgw_creation_with_public_and_private_ip')
    def test_network_appgw_creation_with_public_and_private_ip(self, resource_group):
        self.kwargs.update({
            "appgw": "applicationGateway",
            "ip": "publicIP",
        })

        self.cmd('network public-ip create -g {rg} -n {ip} --sku Standard --ip-tags FirstPartyUsage=/NonProd')

        self.cmd("network application-gateway create -g {rg} -n {appgw} "
                 "--sku Standard_v2 "
                 "--enable-private-link "
                 "--private-ip-address 10.0.0.17 "
                 "--public-ip-address {ip} "
                 "--priority 1001")
        show_data = self.cmd("network application-gateway show -g {rg} -n {appgw}").get_output_in_json()

        self.assertEqual(len(show_data["frontendIPConfigurations"]), 2)

        # Those assertions are not stable, because the order in array frontendIpConfigurations is not fixed
        # self.assertTrue(show_data["frontendIpConfigurations"][0]["publicIpAddress"]["id"].endswith(self.kwargs["ip"]))
        # self.assertTrue(show_data["frontendIpConfigurations"][1]["id"].endswith("appGatewayPrivateFrontendIP"))  # default name
        # self.assertEqual(show_data["frontendIpConfigurations"][1]["privateIpAddress"], "10.0.0.17")
        # self.assertEqual(show_data["frontendIpConfigurations"][1]["privateLinkConfiguration"], None)
        # service buggy, this properties won't be populcated so fast even in Azure CLI 2.12.0
        # self.assertTrue(show_data["frontendIpConfigurations"][1]["privateLinkConfiguration"]["id"].endswith("PrivateLinkDefaultConfiguration"))

        self.cmd("network application-gateway delete -g {rg} -n {appgw}")


class NetworkAppGatewayIndentityScenarioTest(ScenarioTest):

    @live_only()
    @ResourceGroupPreparer(name_prefix='cli_test_ag_identity')
    @KeyVaultPreparer(name_prefix='cli-test-keyvault-', sku='premium')
    def test_network_app_gateway_with_identity(self, resource_group):

        self.kwargs.update({
            'rg': resource_group,
            'gw': 'gateway',
            'one_off_identity': 'id1',
            'access_identity': 'id2',
            'ip': 'ip1',
            'cert': 'MyCertificate'
        })

        # create a managed identity
        self.cmd('identity create -g {rg} -n {one_off_identity}').get_output_in_json()
        access_identity_result = self.cmd('identity create -g {rg} -n {access_identity}').get_output_in_json()
        self.kwargs.update({
            'access_identity_principal': access_identity_result['principalId']
        })

        self.cmd('keyvault set-policy -g {rg} -n {kv} '
                 '--object-id {access_identity_principal} --secret-permissions get list set')

        # create a certificate
        keyvault_cert_policy = self.cmd('az keyvault certificate get-default-policy').get_output_in_json()
        self.kwargs.update({
            'keyvault_cert_policy': keyvault_cert_policy
        })
        self.cmd('keyvault certificate create '
                 '--vault-name {kv} '
                 '--name {cert} '
                 '--policy "{keyvault_cert_policy}"')
        cert_result = self.cmd('keyvault certificate show --vault-name {kv} --name {cert}').get_output_in_json()
        self.kwargs.update({
            'secret_id': cert_result['sid']
        })

        self.cmd('network public-ip create -g {rg} -n {ip} --sku Standard --ip-tags FirstPartyUsage=/NonProd')

        # create application-gateway with one_off_identity
        self.cmd('network application-gateway create '
                 '-g {rg} -n {gw} '
                 '--sku Standard_v2 --public-ip-address {ip} '
                 '--identity {one_off_identity} '
                 '--priority 1001')
        self.cmd('network application-gateway show -g {rg} -n {gw}', checks=[
            self.check('identity.type', 'userAssigned')
        ])

        # remove one_off_identity
        self.cmd('network application-gateway identity remove -g {rg} --gateway-name {gw}', checks=[
            self.check('identity', None)
        ])
        # assign access_identity
        self.cmd('network application-gateway identity assign '
                 '-g {rg} --gateway-name {gw} --identity {access_identity}',
                 checks=[
                     self.check('identity.type', 'userAssigned')
                 ])
        self.cmd('network application-gateway identity show -g {rg} --gateway-name {gw}', checks=[
            self.check('type', 'userAssigned')
        ])

        self.cmd('network application-gateway ssl-cert create '
                 ' -g {rg} --gateway-name {gw} '
                 '--name MySSLCert '
                 '--key-vault-secret-id {secret_id}')

        self.cmd('network application-gateway root-cert create -g {rg} --gateway-name {gw} -n cert1 --keyvault-secret {secret_id}', checks=[
            self.check('trustedRootCertificates[0].keyVaultSecretId', '{secret_id}')
        ])


    @ResourceGroupPreparer(name_prefix='cli_test_ag_cert_name_')
    @KeyVaultPreparer(name_prefix='cli-test-keyvault-', sku='premium', additional_params='--enable-rbac-authorization false')
    def test_network_app_gateway_with_cert_name(self, resource_group):
        self.kwargs.update({
            'rg': resource_group,
            'gw': 'gateway',
            'access_identity': 'id1',
            'ip': 'ip1',
            'cert': 'MyCertificate',
            'ssl_cert_name': 'TestCertName'
        })

        # create a managed identity
        access_identity_result = self.cmd('identity create -g {rg} -n {access_identity}').get_output_in_json()
        self.kwargs.update({
            'access_identity_principal': access_identity_result['principalId']
        })

        self.cmd('keyvault set-policy -g {rg} -n {kv} '
                 '--object-id {access_identity_principal} --secret-permissions get list set')

        # create a certificate
        keyvault_cert_policy = self.cmd('az keyvault certificate get-default-policy').get_output_in_json()
        self.kwargs.update({
            'keyvault_cert_policy': keyvault_cert_policy
        })
        self.cmd('keyvault certificate create '
                 '--vault-name {kv} '
                 '--name {cert} '
                 '--policy "{keyvault_cert_policy}"')
        cert_result = self.cmd('keyvault certificate show --vault-name {kv} --name {cert}').get_output_in_json()
        self.kwargs.update({
            'secret_id': cert_result['sid']
        })

        self.cmd('network public-ip create -g {rg} -n {ip} --sku Standard --ip-tags FirstPartyUsage=/NonProd')

        # create application-gateway with one_off_identity
        self.cmd('network application-gateway create '
                 '-g {rg} -n {gw} '
                 '--sku Standard_v2 --public-ip-address {ip} '
                 '--identity {access_identity} '
                 '--frontend-port 1000 '
                 '--key-vault-secret-id {secret_id} '
                 '--ssl-certificate-name {ssl_cert_name} --priority 1001', checks=[
            self.check('applicationGateway.sslCertificates[0].name', self.kwargs['ssl_cert_name']),
            self.check('applicationGateway.sslCertificates[0].properties.keyVaultSecretId', self.kwargs['secret_id']),
        ])


class NetworkAppGatewayTrustedClientCertScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_ag_trusted_client_cert')
    def test_network_app_gateway_with_trusted_client_cert(self, resource_group):
        self.kwargs.update({
            'rg': resource_group,
            'gw': 'gateway',
            'ip': 'ip1',
            'cert': os.path.join(TEST_DIR, 'client.cer'),
            'cert1': os.path.join(TEST_DIR, 'client1.cer'),
            'cname': 'cert_name',
            'cname1': 'cert_name1',
        })

        # create an ag with trusted client cert
        self.cmd('network public-ip create -g {rg} -n {ip} --sku Standard --ip-tags FirstPartyUsage=/NonProd')
        self.cmd('network application-gateway create -g {rg} -n {gw} --sku Standard_v2 --public-ip-address {ip} '
                 '--trusted-client-cert name={cname} data="{cert}" --priority 1001',
                 checks=[self.check('length(applicationGateway.trustedClientCertificates)', 1)])

        self.cmd('network application-gateway client-cert add -g {rg} --gateway-name {gw} '
                 '--name {cname1} --data "{cert1}"',
                 checks=[self.check('length(trustedClientCertificates)', 2)])

        self.cmd('network application-gateway client-cert list -g {rg} --gateway-name {gw}',
                 checks=[self.check('length(@)', 2)])

        self.cmd('network application-gateway client-cert update -g {rg} --gateway-name {gw} '
                 '--name {cname1} --data "{cert}"')

        cert = self.cmd('network application-gateway client-cert show -g {rg} --gateway-name {gw} --name {cname}').get_output_in_json()

        self.cmd('network application-gateway client-cert show -g {rg} --gateway-name {gw} --name {cname1}',
                 checks=[self.check('data', cert['data'])])

        self.cmd('network application-gateway client-cert remove -g {rg} --gateway-name {gw} --name {cname1}')


class NetworkAppGatewaySslProfileScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_ag_ssl_profile')
    def test_network_app_gateway_with_ssl_profile(self, resource_group):
        self.kwargs.update({
            'rg': resource_group,
            'gw': 'gateway',
            'ip': 'ip1',
            'name': 'name',
            'name1': 'name1',
        })

        # create an ag with ssl profile
        self.cmd('network public-ip create -g {rg} -n {ip} --sku Standard --ip-tags FirstPartyUsage=/NonProd')
        self.cmd(
            "network application-gateway create -n {gw} -g {rg} --public-ip-address {ip} --sku Standard_v2 --priority 1001 "
            "--ssl-profile name={name} min-protocol-version=TLSv1_0 cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 policy-type=Custom client-auth-configuration=True",
            checks=[
                self.check("length(applicationGateway.sslProfiles)", 1),
                self.check("applicationGateway.sslProfiles[0].properties.clientAuthConfiguration.verifyClientCertIssuerDN", True),
                self.check("applicationGateway.sslProfiles[0].properties.clientAuthConfiguration.verifyClientRevocation", "None"),
            ]
        )
        # set client cert revocation option
        self.cmd(
            "network application-gateway update -n {gw} -g {rg} --ssl-profiles [0].client-auth-configuration.verify-client-revocation=OCSP",
            checks=[
                self.check("sslProfiles[0].clientAuthConfiguration.verifyClientCertIssuerDN", True),
                self.check("sslProfiles[0].clientAuthConfiguration.verifyClientRevocation", "OCSP"),
            ]
        )

        self.cmd('network application-gateway ssl-profile add -g {rg} --gateway-name {gw} --name {name1} '
                 '--client-auth-configuration True --min-protocol-version TLSv1_0 '
                 '--cipher-suites TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 --policy-type Custom',
                 checks=[self.check('length(sslProfiles)', 2)])

        self.cmd('network application-gateway ssl-profile update -g {rg} --gateway-name {gw} --name {name1} '
                 '--client-auth-configuration False',
                 checks=[self.check('sslProfiles[1].clientAuthConfiguration.verifyClientCertIssuerDN', False)])

        self.cmd('network application-gateway ssl-profile show -g {rg} --gateway-name {gw} --name {name1} ',
                 checks=[self.check('clientAuthConfiguration.verifyClientCertIssuerDN', False)])

        self.cmd('network application-gateway ssl-profile list -g {rg} --gateway-name {gw}',
                 checks=[self.check('length(@)', 2)])

        self.cmd('network application-gateway ssl-profile remove -g {rg} --gateway-name {gw} --name {name} ')


class NetworkAppGatewayZoneScenario(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_ag_zone', location='westus2')
    def test_network_ag_zone(self, resource_group):
        self.kwargs.update({
            'gateway': 'ag1',
            'ip': 'pubip1'
        })

        # for public-ip after '2020-08-01', when set '-z 1 3', actually return 'zones:[1,2,3]'
        self.cmd('network public-ip create -g {rg} -n {ip} --sku Standard -z 1 3 --ip-tags FirstPartyUsage=/NonProd', checks=[
            self.check('length(publicIp.zones)', 3)
        ])
        self.cmd('network application-gateway create -g {rg} -n {gateway} --sku Standard_v2 --min-capacity 2 --max-capacity 4 --zones 1 3 --public-ip-address {ip} --priority 1001 --no-wait')
        self.cmd('network application-gateway wait -g {rg} -n {gateway} --exists')
        self.cmd('network application-gateway show -g {rg} -n {gateway}', checks=[
            self.check('zones[0]', 1)
        ])


class NetworkAppGatewayAuthCertScenario(ScenarioTest):
    @unittest.skip('not registered for feature Microsoft.Network/AllowBringYourOwnPublicIpAddress required to carry out the requested operation')
    @ResourceGroupPreparer(name_prefix='cli_test_ag_auth_cert')
    def test_network_ag_auth_cert(self, resource_group):
        self.kwargs.update({
            'gateway': 'ag1',
            'ip1': 'ip1',
            'cert1': 'cert1',
            'cert1_file': os.path.join(TEST_DIR, 'AuthCert.pfx'),
            'cert2': 'cert2',
            'cert2_file': os.path.join(TEST_DIR, 'AuthCert2.pfx'),
            'cert3': 'cert3',
            'cert3_file': os.path.join(TEST_DIR, 'AuthCert3.pfx'),
            'settings': 'https_settings'
        })
        self.cmd('network public-ip create -g {rg} -n {ip1} --sku Standard --ip-tags FirstPartyUsage=/NonProd')
        self.cmd('network application-gateway create -g {rg} -n {gateway} --priority 1001 --public-ip-address {ip1} --sku Standard_v2')
        self.cmd('network application-gateway wait -g {rg} -n {gateway} --exists')
        self.cmd('network application-gateway auth-cert create -g {rg} --gateway-name {gateway} -n {cert1} --cert-file "{cert1_file}" --no-wait')
        self.cmd('network application-gateway auth-cert create -g {rg} --gateway-name {gateway} -n {cert2} --cert-file "{cert2_file}" --no-wait')

        self.cmd( 'network application-gateway auth-cert update -g {rg} --gateway-name {gateway} -n {cert1} --cert-file "{cert3_file}" --no-wait')

        # test command of auth-cert list
        self.cmd('network application-gateway auth-cert list -g {rg} --gateway-name {gateway}',
                 checks=self.check('length(@)', 2))

        # test command of auth-cert show
        self.cmd('network application-gateway auth-cert show -g {rg} --gateway-name {gateway} -n {cert1}',
                 checks=self.check('name', 'cert1'))

        # test command of auth-cert delete
        self.cmd('network application-gateway auth-cert delete -g {rg} --gateway-name {gateway} -n {cert1} --no-wait')
        self.cmd('network application-gateway auth-cert list -g {rg} --gateway-name {gateway}',
                 checks=self.check('length(@)', 1))

        self.cmd('network application-gateway auth-cert create -g {rg} --gateway-name {gateway} -n {cert1} --cert-file "{cert1_file}" --no-wait')

        self.cmd('network application-gateway http-settings create -g {rg} --gateway-name {gateway} -n {settings} --auth-certs {cert1} {cert2} --no-wait --port 443 --protocol https')
        self.cmd('network application-gateway http-settings update -g {rg} --gateway-name {gateway} -n {settings} --auth-certs {cert2} {cert1} --no-wait')
        self.cmd('network application-gateway show -g {rg} -n {gateway}',
                 checks=self.check('length(backendHttpSettingsCollection[1].authenticationCertificates)', 2))


class NetworkAppGatewayTrustedRootCertScenario(ScenarioTest):
    @unittest.skip('not registered for feature Microsoft.Network/AllowBringYourOwnPublicIpAddress required to carry out the requested operation')
    @ResourceGroupPreparer(name_prefix='cli_test_ag_root_cert')
    def test_network_ag_root_cert(self, resource_group):
        self.kwargs.update({
            'gateway': 'ag1',
            'cert1': 'cert1',
            'cert1_file': os.path.join(TEST_DIR, 'test-root-cert.cer'),
            'cert2': 'cert2',
            'cert2_file': os.path.join(TEST_DIR, 'test-root-cert-2.cer'),
            'settings': 'https_settings',
            'ip1': 'myip1'
        })
        self.cmd('network public-ip create -g {rg} -n {ip1} --sku Standard --ip-tags FirstPartyUsage=/NonProd')
        self.cmd('network application-gateway create -g {rg} -n {gateway} --sku Standard_v2 --public-ip-address {ip1} --priority 1001')
        self.cmd('network application-gateway wait -g {rg} -n {gateway} --exists')
        self.cmd('network application-gateway root-cert create -g {rg} --gateway-name {gateway} -n {cert1} --cert-file "{cert1_file}"')
        self.cmd('network application-gateway root-cert create -g {rg} --gateway-name {gateway} -n {cert2} --cert-file "{cert2_file}"')

        # test root-cert list
        self.cmd('network application-gateway root-cert list -g {rg} --gateway-name {gateway}',
                 checks=self.check('length(@)', 2))
        # test root-cert show
        self.cmd('network application-gateway root-cert show -g {rg} --gateway-name {gateway} -n {cert1}',
                 checks=self.check('name', 'cert1'))

        # test root-cert delete
        self.cmd('network application-gateway root-cert delete -g {rg} --gateway-name {gateway} -n {cert2} --no-wait')
        self.cmd('network application-gateway root-cert list -g {rg} --gateway-name {gateway}',
                 checks=self.check('length(@)', 1))
        self.cmd('network application-gateway root-cert create -g {rg} --gateway-name {gateway} -n {cert2} --cert-file "{cert2_file}" --no-wait')

        self.cmd('network application-gateway http-settings create -g {rg} --gateway-name {gateway} -n {settings} --root-certs {cert1} {cert2} --host-name-from-backend-pool true --no-wait --port 443 --protocol https')
        self.cmd('network application-gateway http-settings update -g {rg} --gateway-name {gateway} -n {settings} --root-certs {cert2} {cert1} --no-wait')
        self.cmd('network application-gateway show -g {rg} -n {gateway}',
                 checks=self.check('length(backendHttpSettingsCollection[1].trustedRootCertificates)', 2))
        self.cmd('network application-gateway http-settings update -g {rg} --gateway-name {gateway} -n {settings} --no-wait')


class NetworkAppGatewayRedirectConfigScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_ag_basic')
    def test_network_app_gateway_redirect_config(self, resource_group):
        self.kwargs.update({
            'gateway': 'ag1',
            'name': 'redirect1',
            'name2': 'redirect2'
        })
        self.cmd('network application-gateway create -g {rg} -n {gateway} --priority 1001 --no-wait')
        self.cmd('network application-gateway wait -g {rg} -n {gateway} --exists')
        self.cmd('network application-gateway redirect-config create --gateway-name {gateway} -g {rg} -n {name} -t permanent --include-query-string --include-path false --target-listener appGatewayHttpListener --no-wait')
        self.cmd('network application-gateway redirect-config show --gateway-name {gateway} -g {rg} -n {name}', checks=[
            self.check('includePath', False),
            self.check('includeQueryString', True),
            self.check('redirectType', 'Permanent')
        ])
        self.cmd('network application-gateway redirect-config update --gateway-name {gateway} -g {rg} -n {name} --include-path --include-query-string false --no-wait')
        self.cmd('network application-gateway redirect-config show --gateway-name {gateway} -g {rg} -n {name}', checks=[
            self.check('includePath', True),
            self.check('includeQueryString', False),
            self.check('redirectType', 'Permanent')
        ])
        # test redirect-config list command
        self.cmd('network application-gateway redirect-config create --gateway-name {gateway} -g {rg} -n {name2} -t permanent --include-query-string --include-path false --target-listener appGatewayHttpListener --no-wait')
        self.cmd('network application-gateway redirect-config list --gateway-name {gateway} -g {rg}', checks=[
            self.check('length(@)', 2)
        ])
        # test redirect-config delete command
        self.cmd('network application-gateway redirect-config delete --gateway-name {gateway} -g {rg} -n {name2}')
        self.cmd('network application-gateway redirect-config list --gateway-name {gateway} -g {rg}', checks=[
            self.check('length(@)', 1)
        ])



class NetworkAppGatewayExistingSubnetScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_ag_existing_subnet')
    def test_network_app_gateway_with_existing_subnet(self, resource_group):

        vnet = self.cmd('network vnet create -g {rg} -n vnet2 --subnet-name subnet1').get_output_in_json()
        subnet_id = vnet['newVNet']['subnets'][0]['id']
        self.kwargs['subnet_id'] = subnet_id

        # make sure it fails
        self.cmd('network application-gateway create -g {rg} -n ag2 --subnet {subnet_id} --subnet-address-prefix 10.0.0.0/28 --tags foo=doo --priority 1001', expect_failure=True)
        # now verify it succeeds
        self.cmd('network application-gateway create -g {rg} -n ag2 --subnet {subnet_id} --servers 172.0.0.1 www.mydomain.com --priority 1001', checks=[
            self.check('applicationGateway.frontendIPConfigurations[0].properties.privateIPAllocationMethod', 'Dynamic'),
            self.check('applicationGateway.frontendIPConfigurations[0].properties.subnet.id', subnet_id)
        ])


class NetworkAppGatewayNoWaitScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_ag_no_wait')
    def test_network_app_gateway_no_wait(self, resource_group):

        self.kwargs.update({
            'tags': {'a': 'b', 'c': 'd'}
        })

        self.cmd('network application-gateway create -g {rg} -n ag1 --no-wait --connection-draining-timeout 180 --priority 1001', checks=self.is_empty())
        self.cmd('network application-gateway create -g {rg} -n ag2 --no-wait --tags a=b c=d --priority 1001', checks=self.is_empty())
        self.cmd('network application-gateway wait -g {rg} -n ag1 --created --interval 120', checks=self.is_empty())
        self.cmd('network application-gateway wait -g {rg} -n ag2 --created --interval 120', checks=self.is_empty())
        self.cmd('network application-gateway show -g {rg} -n ag1', checks=[
            self.check('provisioningState', 'Succeeded'),
            self.check('backendHttpSettingsCollection[0].connectionDraining.enabled', True),
            self.check('backendHttpSettingsCollection[0].connectionDraining.drainTimeoutInSec', 180)
        ])
        self.cmd('network application-gateway show -g {rg} -n ag2', checks=[
            self.check('provisioningState', 'Succeeded'),
            self.check('tags', '{tags}')
        ])
        self.cmd('network application-gateway delete -g {rg} -n ag2 --no-wait')
        self.cmd('network application-gateway wait -g {rg} -n ag2 --deleted')


class NetworkAppGatewayPrivateIpScenarioTest20170601(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_ag_private_ip')
    def test_network_app_gateway_with_private_ip(self, resource_group):

        self.kwargs.update({
            'private_ip': '10.0.0.15',
            'public_ip': 'pip-ag3',
            'path': os.path.join(TEST_DIR, 'TestCert.pfx'),
            'pass': 'password'
        })
        self.cmd('network public-ip create -g {rg} -n {public_ip} --sku Standard')
        self.cmd('network application-gateway waf-policy create -n waf1 -g {rg}')
        self.cmd('network application-gateway create -g {rg} -n ag3 --subnet subnet1 --private-ip-address {private_ip} --public-ip-address {public_ip} --sku WAF_v2 --waf-policy waf1 --cert-file "{path}" --cert-password {pass} --priority 1001 --no-wait')
        self.cmd('network application-gateway wait -g {rg} -n ag3 --exists')
        self.cmd('network application-gateway show -g {rg} -n ag3', checks=[
            self.check('frontendIPConfigurations[0].privateIPAddress', '{private_ip}'),
            self.check('frontendIPConfigurations[0].privateIPAllocationMethod', 'Static')
        ])
        self.kwargs['path'] = os.path.join(TEST_DIR, 'TestCert2.pfx')
        self.cmd('network application-gateway ssl-cert update -g {rg} --gateway-name ag3 -n ag3SslCert --cert-file "{path}" --cert-password {pass}')
        self.cmd('network application-gateway wait -g {rg} -n ag3 --updated')

        # test ssl-cert list
        self.cmd('network application-gateway ssl-cert list -g {rg} --gateway-name ag3',
                 checks=[self.check('length(@)', 1)])

        # test ssl-cert show
        self.cmd('network application-gateway ssl-cert show -g {rg} --gateway-name ag3 -n ag3SslCert',
                 checks=[self.check('name', 'ag3SslCert')])

        self.kwargs['path'] = os.path.join(TEST_DIR, 'TestCert.pfx')
        self.cmd('network application-gateway ssl-cert create -g {rg} --gateway-name ag3 -n ag3SslCert01 --cert-file "{path}" --cert-password {pass} --no-wait')
        # test ssl-cert delete
        self.cmd('network application-gateway ssl-cert delete -g {rg} --gateway-name ag3 -n ag3SslCert01 --no-wait')
        self.cmd('network application-gateway ssl-cert list -g {rg} --gateway-name ag3', checks=[
            self.check('length(@)', 1)])

        self.cmd('network application-gateway ssl-policy set -g {rg} --gateway-name ag3 --disabled-ssl-protocols TLSv1_0 TLSv1_1 --no-wait')
        self.cmd('network application-gateway ssl-policy show -g {rg} --gateway-name ag3',
                 checks=self.check('disabledSslProtocols.length(@)', 2))

        cipher_suite = 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256'
        self.kwargs['cipher'] = cipher_suite
        self.cmd('network application-gateway ssl-policy set -g {rg} --gateway-name ag3 --min-protocol-version TLSv1_2 --cipher-suites {cipher} --no-wait')
        self.cmd('network application-gateway ssl-policy show -g {rg} --gateway-name ag3', checks=[
            self.check('cipherSuites.length(@)', 1),
            self.check('minProtocolVersion', 'TLSv1_2'),
            self.check('policyType', 'Custom')
        ])

        # supported predefined policy (positive path)
        policy_name = 'AppGwSslPolicy20220101'
        self.kwargs['policy'] = policy_name
        self.cmd('network application-gateway ssl-policy set -g {rg} --gateway-name ag3 -n {policy} --policy-type Predefined --no-wait')
        self.cmd('network application-gateway wait -g {rg} -n ag3 --updated')
        self.cmd('network application-gateway ssl-policy show -g {rg} --gateway-name ag3', checks=[
            self.check('policyName', policy_name),
            self.check('policyType', 'Predefined')
        ])
        # test predefined show
        self.cmd('network application-gateway ssl-policy predefined show -n {policy}', checks=[
            self.check('name', policy_name)
        ])

        # test predefined list
        self.cmd('network application-gateway ssl-policy predefined list', checks=[
            self.check('length(@)', 5)])

        # test ssl-policy list-options
        self.cmd('network application-gateway ssl-policy list-options', checks=[
            self.exists('availableCipherSuites'),
            self.exists('availableProtocols'),
            self.exists('predefinedPolicies'),
            self.check('type', 'Microsoft.Network/ApplicationGatewayAvailableSslOptions'),
        ])

    @ResourceGroupPreparer(name_prefix='test_appgw_with_tcp', location='westus')
    def test_appgw_with_tcp(self, resource_group):
        self.kwargs.update({
            'appgw': 'appgw',
            'appgw_frontend_port': 'testFrontendPort',
            'appgw_settings': 'testSettings',
            'appgw_listener': 'testListener',
            'appgw_address_pool': 'testAddressPool',
            'appgw_routing_rule': 'testRule',
            'appgw_public_ip': 'testPublicIp',
            'appgw_rule_type': 'Basic',
            'priority': 1001,
            'port': 8080
        })

        self.cmd('network public-ip create -g {rg} -n {appgw_public_ip} --sku Standard --ip-tags FirstPartyUsage=/NonProd')

        self.cmd('network application-gateway create -g {rg} -n {appgw} '
                 '--public-ip-address {appgw_public_ip} --sku Standard_v2 '
                 '--priority {priority}')
        show_appgw_data = self.cmd('network application-gateway show -g {rg} -n {appgw}').get_output_in_json()
        frontend_ip = show_appgw_data['frontendIPConfigurations'][0]['name']
        self.kwargs.update({
            'appgw_frontend_ip': frontend_ip
        })

        self.cmd('network application-gateway frontend-port create -g {rg} --gateway-name {appgw} '
                 '-n {appgw_frontend_port} --port {port}')
        self.cmd('network application-gateway listener create -g {rg} --gateway-name {appgw} '
                 '--frontend-port {appgw_frontend_port} -n {appgw_listener} --frontend-ip {appgw_frontend_ip}',
                 checks=(self.check('listeners[0].name', '{appgw_listener}')))
        self.cmd('network application-gateway settings create -g {rg} --gateway-name {appgw} '
                 '--name {appgw_settings} --port {port} ',
                 checks=(self.check('backendSettingsCollection[0].name', '{appgw_settings}')))
        self.cmd(
            'network application-gateway address-pool create -g {rg} --gateway-name {appgw} -n {appgw_address_pool} '
            '--servers 10.0.0.4 10.0.0.5')
        self.cmd('network application-gateway routing-rule create -g {rg} --gateway-name {appgw} '
                 '--name {appgw_routing_rule} --listener {appgw_listener} --rule-type {appgw_rule_type} '
                 '--address-pool {appgw_address_pool} --settings {appgw_settings} --priority 1002',
                 checks=[
                     self.check('routingRules[0].name', '{appgw_routing_rule}')
                 ])

        self.cmd('network application-gateway delete --name {appgw} --resource-group {rg}')

class NetworkAppGatewaySslCertManagedHsmScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_ag_ssl_cert_hsm', location='uksouth')
    def test_network_app_gateway_ssl_cert_managed_hsm(self, resource_group):
        logged_in_user = self.cmd('ad signed-in-user show').get_output_in_json()
        init_admin = logged_in_user['id'] if logged_in_user is not None else ''

        self.kwargs.update({
            'ag': 'ag-hsm-test',
            'ip': 'pip-hsm-test',
            'identity': 'id-hsm-test',
            'hsm_name': self.create_random_name('clihsm', 24),
            'init_admin': init_admin,
            'cert_name': 'hsmSslCert',
            'cert_name2': 'hsmSslCert2',
        })

        # create managed identity
        identity_result = self.cmd('identity create -g {rg} -n {identity}').get_output_in_json()
        self.kwargs['identity_id'] = identity_result['id']
        self.kwargs['identity_principal'] = identity_result['principalId']

        # create Managed HSM
        self.cmd('keyvault create --hsm-name {hsm_name} -g {rg} -l uksouth '
                 '--administrators {init_admin} --retention-days 7')

        # activate HSM by downloading security domain
        cert_dir = os.path.join(TEST_DIR, 'certs')
        tmp_dir = tempfile.mkdtemp()
        self.kwargs.update({
            'sd_cert0': os.path.join(cert_dir, 'cert_0.cer').replace('\\', '\\\\'),
            'sd_cert1': os.path.join(cert_dir, 'cert_1.cer').replace('\\', '\\\\'),
            'sd_cert2': os.path.join(cert_dir, 'cert_2.cer').replace('\\', '\\\\'),
            'security_domain': os.path.join(tmp_dir, 'sd.json').replace('\\', '\\\\'),
        })
        self.cmd('keyvault security-domain download --hsm-name {hsm_name} '
                 '--sd-wrapping-keys {sd_cert0} {sd_cert1} {sd_cert2} '
                 '--sd-quorum 2 --security-domain-file {security_domain}')

        # grant signed-in user and identity access to create keys in HSM
        from unittest import mock
        with mock.patch('azure.cli.command_modules.keyvault.custom._gen_guid', side_effect=self.create_guid):
            self.cmd('keyvault role assignment create --hsm-name {hsm_name} '
                     '--role "Managed HSM Crypto User" '
                     '--assignee {init_admin} --scope /keys')
            self.cmd('keyvault role assignment create --hsm-name {hsm_name} '
                     '--role "Managed HSM Crypto User" '
                     '--assignee {identity_principal} --scope /keys')

        # create keys in Managed HSM
        kid = self.cmd('keyvault key create --hsm-name {hsm_name} -n mykey1'
                       ).get_output_in_json()['key']['kid']
        kid2 = self.cmd('keyvault key create --hsm-name {hsm_name} -n mykey2'
                        ).get_output_in_json()['key']['kid']
        self.kwargs.update({
            'hsm_key_id': kid,
            'hsm_key_id2': kid2,
        })

        # read public cert data from existing test cert file
        cert_file = os.path.join(TEST_DIR, 'certs', 'cert_0.cer')
        with open(cert_file, 'r') as f:
            lines = f.read().strip().split('\n')
        pub_cert_data = ''.join(l.strip() for l in lines if not l.startswith('-----'))
        self.kwargs['pub_cert_data'] = pub_cert_data

        # create public IP and application gateway with identity
        self.cmd('network public-ip create -g {rg} -n {ip} --sku Standard')
        self.cmd('network application-gateway create -g {rg} -n {ag} '
                 '--sku Standard_v2 --public-ip-address {ip} '
                 '--identity {identity_id} --priority 1001 --no-wait')
        self.cmd('network application-gateway wait -g {rg} -n {ag} --exists')

        # test validation: --hsm key-id without public-cert-data should fail
        self.cmd('network application-gateway ssl-cert create -g {rg} --gateway-name {ag} '
                 '-n badCert --hsm key-id={hsm_key_id}',
                 expect_failure=True)

        # test ssl-cert create with --hsm key-id and public-cert-data
        self.cmd('network application-gateway ssl-cert create -g {rg} --gateway-name {ag} '
                 '-n {cert_name} --hsm key-id={hsm_key_id} public-cert-data={pub_cert_data}',
                 checks=[
                     self.check('name', '{cert_name}'),
                     self.check('hsm.keyId', '{hsm_key_id}'),
                 ])

        # test ssl-cert show returns hsm block
        self.cmd('network application-gateway ssl-cert show -g {rg} --gateway-name {ag} '
                 '-n {cert_name}',
                 checks=[
                     self.check('name', '{cert_name}'),
                     self.check('hsm.keyId', '{hsm_key_id}'),
                     self.exists('hsm'),
                 ])

        # test ssl-cert update to change hsm key-id
        self.cmd('network application-gateway ssl-cert update -g {rg} --gateway-name {ag} '
                 '-n {cert_name} --hsm key-id={hsm_key_id2} public-cert-data={pub_cert_data}',
                 checks=[
                     self.check('name', '{cert_name}'),
                     self.check('hsm.keyId', '{hsm_key_id2}'),
                 ])

        # test ssl-cert list includes the hsm cert
        self.cmd('network application-gateway ssl-cert list -g {rg} --gateway-name {ag}',
                 checks=[
                     self.check('length(@)', 1),
                     self.check('[0].name', '{cert_name}'),
                     self.check('[0].hsm.keyId', '{hsm_key_id2}'),
                 ])

        # test ssl-cert create a second hsm cert
        self.cmd('network application-gateway ssl-cert create -g {rg} --gateway-name {ag} '
                 '-n {cert_name2} --hsm key-id={hsm_key_id} public-cert-data={pub_cert_data}',
                 checks=[
                     self.check('name', '{cert_name2}'),
                     self.check('hsm.keyId', '{hsm_key_id}'),
                 ])
        self.cmd('network application-gateway ssl-cert list -g {rg} --gateway-name {ag}',
                 checks=[self.check('length(@)', 2)])

        # test ssl-cert delete
        self.cmd('network application-gateway ssl-cert delete -g {rg} --gateway-name {ag} '
                 '-n {cert_name2} --no-wait')
        self.cmd('network application-gateway wait -g {rg} -n {ag} --updated')
        self.cmd('network application-gateway ssl-cert list -g {rg} --gateway-name {ag}',
                 checks=[self.check('length(@)', 1)])


class NetworkAppGatewaySubresourceScenarioTest(ScenarioTest):

    def _create_ag(self):
        self.cmd('network application-gateway create -g {rg} -n {ag} --priority 1001 --no-wait')
        self.cmd('network application-gateway wait -g {rg} -n {ag} --exists')

    @ResourceGroupPreparer(name_prefix='cli_test_ag_address_pool')
    def test_network_ag_address_pool(self, resource_group):

        self.kwargs.update({
            'ag': 'ag1',
            'res': 'application-gateway address-pool',
            'name': 'pool1'
        })
        self._create_ag()

        self.cmd('network {res} create -g {rg} --gateway-name {ag} -n {name} --no-wait --servers 123.4.5.6 www.mydns.com')
        self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('length(backendAddresses)', 2),
            self.check('backendAddresses[0].ipAddress', '123.4.5.6'),
            self.check('backendAddresses[1].fqdn', 'www.mydns.com'),
        ])
        self.cmd('network {res} update -g {rg} --gateway-name {ag} -n {name} --no-wait --servers 5.4.3.2')
        self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('length(backendAddresses)', 1),
            self.check('backendAddresses[0].ipAddress', '5.4.3.2')
        ])
        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 2))
        self.cmd('network {res} delete -g {rg} --gateway-name {ag} --no-wait -n {name}')
        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 1))

    @ResourceGroupPreparer(name_prefix='cli_test_ag_frontend_port')
    def test_network_ag_frontend_port(self, resource_group):

        self.kwargs.update({
            'ag': 'ag1',
            'res': 'application-gateway frontend-port',
            'name': 'myport'
        })
        self._create_ag()

        self.cmd('network {res} create -g {rg} --gateway-name {ag} -n {name} --no-wait --port 111')
        self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('name', 'myport'),
            self.check('port', 111)
        ])
        self.cmd('network {res} update -g {rg} --gateway-name {ag} -n {name} --no-wait --port 112')
        self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('name', 'myport'),
            self.check('port', 112)
        ])
        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 2))
        self.cmd('network {res} delete -g {rg} --gateway-name {ag} --no-wait -n {name}')
        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 1))

    @ResourceGroupPreparer(name_prefix='cli_test_ag_frontend_ip_public')
    def test_network_ag_frontend_ip_public(self, resource_group):

        self.kwargs.update({
            'ag': 'ag1',
            'res': 'application-gateway frontend-ip',
            'name': 'myfrontend',
            'ip1': 'myip1',
            'ip2': 'myip2'
        })
        self.cmd('network application-gateway create -g {rg} -n {ag} --priority 1001 --no-wait')
        self.cmd('network application-gateway wait -g {rg} -n {ag} --exists')

        self.cmd('network public-ip create -g {rg} -n {ip1} --sku Basic')
        self.cmd('network public-ip create -g {rg} -n {ip2}')

        self.cmd('network {res} create -g {rg} --gateway-name {ag} -n {name} --no-wait --public-ip-address {ip1}')
        self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('subnet', None)
        ])

        # NOTE: Service states that public IP address cannot be changed. https://github.com/Azure/azure-cli/issues/4133
        # self.cmd('network {res} update -g {rg} --gateway-name {ag} -n {name} --no-wait --public-ip-address {ip2}')
        # self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}')

        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 2))
        self.cmd('network {res} delete -g {rg} --gateway-name {ag} --no-wait -n {name}')
        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 1))

    @ResourceGroupPreparer(name_prefix='cli_test_ag_frontend_ip_private')
    def test_network_ag_frontend_ip_private(self, resource_group):

        self.kwargs.update({
            'ag': 'ag1',
            'res': 'application-gateway frontend-ip',
            'name': 'frontendip',
            'ip1': 'myip1',
            'vnet1': 'vnet1',
            'vnet2': 'vnet2',
            'subnet': 'subnet1'
        })
        self.cmd('network public-ip create -g {rg} -n {ip1}')
        self.cmd('network vnet create -g {rg} -n {vnet1} --subnet-name {subnet}')

        self.cmd('network application-gateway create -g {rg} -n {ag} --no-wait --public-ip-address {ip1} --vnet-name {vnet1} --subnet {subnet} --priority 1001')
        self.cmd('network application-gateway wait -g {rg} -n {ag} --exists')

        self.cmd('network {res} create -g {rg} --gateway-name {ag} -n {name} --no-wait --private-ip-address 10.0.0.10 --vnet-name {vnet1} --subnet {subnet}')
        self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}', checks=[
        ])

        # NOTE: Service states that frontend subnet cannot differ from gateway subnet https://github.com/Azure/azure-cli/issues/4134
        # self.cmd('network vnet create -g {rg} -n {vnet2} --subnet-name {subnet} --address-prefix 10.0.0.0/16 --subnet-prefix 10.0.10.0/24')
        # self.cmd('network {res} update -g {rg} --gateway-name {ag} -n {name} --no-wait --private-ip-address 11.0.10.10 --vnet-name {vnet2} --subnet {subnet}')
        # self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}')

        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 2))
        self.cmd('network {res} delete -g {rg} --gateway-name {ag} --no-wait -n {name}')
        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 1))

    @ResourceGroupPreparer(name_prefix='cli_test_ag_http_listener')
    def test_network_ag_http_listener(self, resource_group):

        self.kwargs.update({
            'ag': 'ag1',
            'res': 'application-gateway http-listener',
            'name': 'mylistener'
        })
        self._create_ag()

        self.cmd('network {res} create -g {rg} --gateway-name {ag} -n {name} --no-wait --frontend-port appGatewayFrontendPort --host-name www.test.com')
        self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('hostName', 'www.test.com')
        ])
        self.cmd('network {res} update -g {rg} --gateway-name {ag} -n {name} --no-wait --host-name www.test2.com')
        self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('hostName', 'www.test2.com')
        ])
        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 2))
        self.cmd('network {res} delete -g {rg} --gateway-name {ag} --no-wait -n {name}')
        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 1))

    @ResourceGroupPreparer(name_prefix='test_network_ag_http_listener_with_waf_policy')
    def test_network_ag_http_listener_with_waf_policy(self):

        self.kwargs.update({
            'ag': 'ag1',
            'res': 'application-gateway http-listener',
            'name': 'mylistener',
            'waf_1': 'waf_1',
            'waf_2': 'waf_2',
            'waf_3': 'waf_3',
            'listener_2': 'listener_2',
        })

        # prepare 2 WAF policies
        self.cmd('network application-gateway waf-policy create -g {rg} --name {waf_1}')
        self.cmd('network application-gateway waf-policy create -g {rg} --name {waf_2}')
        self.cmd('network application-gateway waf-policy create -g {rg} --name {waf_3}')

        self.cmd('network public-ip create -g {rg} -n ip-1 --sku Standard')

        # sku=WAF_v2 is necessary for updating HTTP listener's WAF configuration
        self.cmd('network application-gateway waf-policy create -n waf_1 -g {rg}')
        create_res = self.cmd('network application-gateway create -g {rg} --name {ag} --public-ip-address ip-1 --sku WAF_v2 --priority 1001 --waf-policy waf_1').get_output_in_json()
        self.assertEqual(len(create_res['applicationGateway']['httpListeners']), 1)
        self.assertIsNone(create_res['applicationGateway']['httpListeners'][0].get('firewallPolicy'))

        # update the default HTTP listener's WAF policy
        update_res = self.cmd('network application-gateway http-listener update -g {rg} --gateway-name {ag} --name appGatewayHttpListener --waf-policy {waf_1}').get_output_in_json()
        self.assertTrue(update_res['firewallPolicy']['id'].endswith('waf_1'))

        # create another HTTP listener with WAF policy and update it to another WAF policy
        self.cmd('network application-gateway frontend-port create -g {rg} --gateway-name {ag} --port 9020 --name 9020')
        self.cmd('network application-gateway http-listener create -g {rg} --gateway-name {ag} --name {listener_2} --frontend-port 9020 --waf-policy {waf_2}')
        update_res = self.cmd('network application-gateway http-listener update -g {rg} --gateway-name {ag} --name {listener_2} --waf-policy {waf_3}').get_output_in_json()
        self.assertTrue(update_res['firewallPolicy']['id'].endswith('waf_3'))

        self.cmd('network application-gateway show -g {rg} --name {ag}')

    @ResourceGroupPreparer(name_prefix='cli_test_ag_http_listener')
    def test_network_ag_http_listener_with_multi_host_names(self, resource_group):

        self.kwargs.update({
            'ag': 'ag1',
            'res': 'application-gateway http-listener',
            'name': 'mylistener',
            'gateway_ip': 'ip1',
            'port': 'cliport',
            'waf': 'waf1',
        })

        self.cmd('network public-ip create -g {rg} -n {gateway_ip} --sku Standard')
        self.cmd('network application-gateway waf-policy create -n {waf} -g {rg}')
        self.cmd('network application-gateway create -g {rg} -n {ag} '
                 '--sku WAF_v2 '
                 '--public-ip-address {gateway_ip} --waf-policy {waf} --priority 1001')
        self.cmd('network application-gateway frontend-port create -g {rg} --gateway-name {ag} -n {port} --port 18080')

        self.cmd('network {res} create -g {rg} --gateway-name {ag} -n {name} --frontend-port {port} --host-names "*.contoso.com" "www.microsoft.com"')
        self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('length(hostNames)', 2),
            self.check('hostNames[0]', "*.contoso.com"),
            self.check('hostNames[1]', "www.microsoft.com")
        ])
        self.cmd('network {res} update -g {rg} --gateway-name {ag} -n {name} --host-names "*.contoso.com" "www.bing.com"')
        self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('length(hostNames)', 2),
            self.check('hostNames[0]', "*.contoso.com"),
            self.check('hostNames[1]', "www.bing.com")
        ])
        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 2))
        self.cmd('network {res} delete -g {rg} --gateway-name {ag} --no-wait -n {name}')
        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 1))

    @ResourceGroupPreparer(name_prefix='cli_test_ag_http_settings')
    def test_network_ag_http_settings(self, resource_group):

        self.kwargs.update({
            'ag': 'ag1',
            'res': 'application-gateway http-settings',
            'name': 'mysettings',
            'name2': 'mysettings2',
            'ip': 'pip',
            'vnet': 'vnet1',
            'subnet': 'subnet1'
        })
        self.cmd('network public-ip create -g {rg} -n {ip} --sku Standard --ip-tags FirstPartyUsage=/NonProd')
        self.cmd('network vnet create -g {rg} -n {vnet} --address-prefix 10.0.0.0/16')
        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} -n {subnet} --address-prefix 10.0.0.0/24 --default-outbound-access false')
        self.cmd('network application-gateway create -g {rg} -n {ag} --vnet-name {vnet} --subnet {subnet} --public-ip-address {ip} --priority 1001 --sku Standard_v2')

        self.cmd('network {res} create -g {rg} --gateway-name {ag} -n {name} --no-wait --affinity-cookie-name mycookie --connection-draining-timeout 60 --cookie-based-affinity --host-name-from-backend-pool --protocol https --timeout 50 --port 70')
        self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('affinityCookieName', 'mycookie'),
            self.check('connectionDraining.drainTimeoutInSec', 60),
            self.check('connectionDraining.enabled', True),
            self.check('cookieBasedAffinity', 'Enabled'),
            self.check('pickHostNameFromBackendAddress', True),
            self.check('port', 70),
            self.check('protocol', 'Https'),
            self.check('requestTimeout', 50)
        ])
        self.cmd('network {res} update -g {rg} --gateway-name {ag} -n {name} --no-wait --affinity-cookie-name mycookie2 --connection-draining-timeout 0 --cookie-based-affinity disabled --host-name-from-backend-pool false --protocol http --timeout 40 --port 71')
        self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('affinityCookieName', 'mycookie2'),
            self.check('connectionDraining.drainTimeoutInSec', 1),
            self.check('connectionDraining.enabled', False),
            self.check('cookieBasedAffinity', 'Disabled'),
            self.check('pickHostNameFromBackendAddress', False),
            self.check('port', 71),
            self.check('protocol', 'Http'),
            self.check('requestTimeout', 40)
        ])
        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 2))
        self.cmd('network {res} delete -g {rg} --gateway-name {ag} --no-wait -n {name}')
        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 1))

        self.cmd('network application-gateway http-settings create -g {rg} --gateway-name {ag} -n {name2} --port 443 \
                 --protocol Https --cookie-based-affinity disabled --validate-cert-chain-and-expiry false --validate-sni true', checks=[
            self.check('name', '{name2}'),
            self.check('port', 443),
            self.check('protocol', 'Https'),
            self.check('cookieBasedAffinity', 'Disabled'),
            self.check('validateCertChainAndExpiry', False),
            self.check('validateSNI', True),
        ])

    @ResourceGroupPreparer(name_prefix='cli_test_ag_probe')
    def test_network_ag_probe(self, resource_group):

        self.kwargs.update({
            'rg': resource_group,
            'gateway_ip': 'gateway_ip',
            'ag': 'ag1',
            'name': 'myprobe',
            'waf': 'waf1',
        })

        self.cmd('network public-ip create -g {rg} -n {gateway_ip} --sku Standard')
        self.cmd('network application-gateway waf-policy create -n {waf} -g {rg}')
        self.cmd('network application-gateway create -g {rg} -n {ag} '
                 '--sku WAF_v2 --priority 1001 '
                 '--public-ip-address {gateway_ip} --waf-policy {waf}')

        self.cmd('network application-gateway probe create -g {rg} --gateway-name {ag} -n {name} --no-wait '
                 '--path /test '
                 '--protocol http '
                 '--interval 25 '
                 '--timeout 100 '
                 '--threshold 10 '
                 '--min-servers 2 '
                 '--host www.test.com '
                 '--match-status-codes 200 204 '
                 '--host-name-from-http-settings false '
                 '--port 2048 ')
        self.cmd('network application-gateway probe show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('path', '/test'),
            self.check('protocol', 'Http'),
            self.check('interval', 25),
            self.check('timeout', 100),
            self.check('unhealthyThreshold', 10),
            self.check('minServers', 2),
            self.check('host', 'www.test.com'),
            self.check('length(match.statusCodes)', 2),
            self.check('pickHostNameFromBackendHttpSettings', False),
            self.check('port', 2048)
        ])
        self.cmd('network application-gateway probe update -g {rg} --gateway-name {ag} -n {name} --no-wait '
                 '--path /test2 '
                 '--protocol https '
                 '--interval 26 '
                 '--timeout 101 '
                 '--threshold 11 '
                 '--min-servers 3 '
                 '--host "" '
                 '--match-status-codes 201 '
                 '--host-name-from-http-settings '
                 '--port 4096 ')
        self.cmd('network application-gateway probe show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('path', '/test2'),
            self.check('protocol', 'Https'),
            self.check('interval', 26),
            self.check('timeout', 101),
            self.check('unhealthyThreshold', 11),
            self.check('minServers', 3),
            self.check('host', ''),
            self.check('length(match.statusCodes)', 1),
            self.check('pickHostNameFromBackendHttpSettings', True),
            self.check('port', 4096)
        ])
        self.cmd('network application-gateway probe list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 1))
        self.cmd('network application-gateway probe delete -g {rg} --gateway-name {ag} --no-wait -n {name}')
        self.cmd('network application-gateway probe list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 0))

    @ResourceGroupPreparer(name_prefix='cli_test_ag_probe_with_host_name_from_settings')
    def test_network_ag_probe_with_host_name_from_settings(self, resource_group):

        self.kwargs.update({
            'rg': resource_group,
            'gateway_ip': 'gateway_ip',
            'ag': 'ag1',
            'name': 'myprobe'
        })

        self.cmd('network public-ip create -g {rg} -n {gateway_ip} --sku Standard')
        self.cmd('network application-gateway create -g {rg} -n {ag} '
                 '--sku Standard_v2 --priority 1001 '
                 '--public-ip-address {gateway_ip} ')

        self.cmd('network application-gateway probe create -g {rg} --gateway-name {ag} -n {name} --no-wait '
                 '--protocol tcp '
                 '--interval 25 '
                 '--timeout 100 '
                 '--threshold 10 '
                 '--min-servers 2 '
                 '--match-status-codes 200 204 '
                 '--host-name-from-settings false '
                 '--port 2048 ')
        self.cmd('network application-gateway probe show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('protocol', 'Tcp'),
            self.check('interval', 25),
            self.check('timeout', 100),
            self.check('unhealthyThreshold', 10),
            self.check('minServers', 2),
            self.check('length(match.statusCodes)', 2),
            self.check('pickHostNameFromBackendSettings', False),
            self.check('port', 2048)
        ])
        self.cmd('network application-gateway probe update -g {rg} --gateway-name {ag} -n {name} --no-wait '
                 '--protocol tls '
                 '--interval 26 '
                 '--timeout 101 '
                 '--threshold 11 '
                 '--min-servers 3 '
                 '--match-status-codes 201 '
                 '--host-name-from-settings false '
                 '--port 4096 ')
        self.cmd('network application-gateway probe show -g {rg} --gateway-name {ag} -n {name}', checks=[
            self.check('protocol', 'Tls'),
            self.check('interval', 26),
            self.check('timeout', 101),
            self.check('unhealthyThreshold', 11),
            self.check('minServers', 3),
            self.check('length(match.statusCodes)', 1),
            self.check('pickHostNameFromBackendSettings', False),
            self.check('port', 4096)
        ])
        self.cmd('network application-gateway probe list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 1))
        self.cmd('network application-gateway probe delete -g {rg} --gateway-name {ag} --no-wait -n {name}')
        self.cmd('network application-gateway probe list -g {rg} --gateway-name {ag}', checks=self.check('length(@)', 0))

    @ResourceGroupPreparer(name_prefix='cli_test_ag_rule')
    def test_network_ag_rule(self, resource_group):

        self.kwargs.update({
            'ip': 'pip1',
            'ag': 'ag1',
            'res': 'application-gateway rule',
            'name': 'myrule',
            'name2': 'myrule2',
            'set': 'myruleset'
        })
        self.cmd('network public-ip create -g {rg} -n {ip} --sku Standard')
        self.cmd('network application-gateway create -g {rg} -n {ag} --public-ip-address {ip} --sku Standard_v2 --priority 1001 --no-wait')
        self.cmd('network application-gateway wait -g {rg} -n {ag} --exists')

        # Make the default rule has priority.
        # Otherwise, server will raise ApplicationGatewayRequestRoutingRulePartialPriorityDefined
        self.cmd('network {res} update -g {rg} --gateway-name {ag} -n rule1 --priority 1')

        self.cmd('network application-gateway http-listener create -g {rg} --gateway-name {ag} -n mylistener --no-wait --frontend-port appGatewayFrontendPort --host-name www.test.com')
        self.cmd('network application-gateway http-listener create -g {rg} --gateway-name {ag} -n mylistener2 --no-wait --frontend-port appGatewayFrontendPort --host-name www.test2.com')

        self.cmd('network {res} create -g {rg} --gateway-name {ag} -n {name} --no-wait --http-listener mylistener --priority 12')
        rule = self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}').get_output_in_json()
        self.assertTrue(rule['httpListener']['id'].endswith('mylistener'))
        self.cmd('network {res} update -g {rg} --gateway-name {ag} -n {name} --no-wait --http-listener mylistener2 --priority 32')
        rule = self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name}').get_output_in_json()
        self.assertTrue(rule['httpListener']['id'].endswith('mylistener2'))

        self.cmd('network application-gateway rewrite-rule set create -g {rg} --gateway-name {ag} -n {set}')

        # test rewrite-rule set update command
        self.cmd('network application-gateway rewrite-rule set update -g {rg} --gateway-name {ag} -n {set}')

        self.cmd('network {res} create -g {rg} --gateway-name {ag} -n {name2} --no-wait --rewrite-rule-set {set} --http-listener mylistener --priority 10')
        rule = self.cmd('network {res} show -g {rg} --gateway-name {ag} -n {name2}').get_output_in_json()
        self.kwargs['set_id'] = rule['rewriteRuleSet']['id']
        self.cmd('network {res} update -g {rg} --gateway-name {ag} -n {name2} --rewrite-rule-set {set_id} --priority 21', checks=[
            self.check('rewriteRuleSet.id', '{set_id}')
        ])

        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=[
            self.check('length(@)', 3)
        ])
        self.cmd('network {res} delete -g {rg} --gateway-name {ag} --no-wait -n {name}')
        self.cmd('network {res} list -g {rg} --gateway-name {ag}', checks=[
            self.check('length(@)', 2)
        ])

    @ResourceGroupPreparer(name_prefix="cli_test_ag_rule_default_exists", location="westus")
    def test_ag_rule_default_exists(self):
        self.kwargs.update({
            "pip": self.create_random_name("public-ip-", 16),
            "ag": self.create_random_name("application-gateway-", 24),
            "port1": self.create_random_name("frontend-port-", 20),
            "port2": self.create_random_name("frontend-port-", 20),
            "listener": self.create_random_name("listener-", 16),
            "settings": self.create_random_name("settings-", 16),
            "http_listener": self.create_random_name("http-listener-", 20),
            "routing_rule": self.create_random_name("routing-rule-", 20),
            "pool": self.create_random_name("pool-", 12),
            "redirect_config": self.create_random_name("redirect-config-", 20),
            "rule": self.create_random_name("rule-", 12),
        })
        self.cmd("network public-ip create -n {pip} -g {rg} --sku Standard")
        output = self.cmd("network application-gateway create -n {ag} -g {rg} --public-ip-address {pip} --sku Standard_v2 --priority 1001").get_output_in_json()["applicationGateway"]
        self.kwargs["pool_id"] = output["backendAddressPools"][0]["id"]
        self.kwargs["http_settings_id"] = output["backendHttpSettingsCollection"][0]["id"]

        self.cmd("network application-gateway frontend-port create -n {port1} -g {rg} --gateway-name {ag} --port 8080")
        self.kwargs["listener_id"] = self.cmd("network application-gateway listener create -n {listener} -g {rg} --gateway-name {ag} --frontend-port {port1} --frontend-ip appGatewayFrontendIP").get_output_in_json()["listeners"][0]["id"]
        self.kwargs["settings_id"] = self.cmd("network application-gateway settings create -n {settings} -g {rg} --gateway-name {ag} --port 8080").get_output_in_json()["backendSettingsCollection"][0]["id"]

        self.cmd(
            "network application-gateway routing-rule create -n {routing_rule} -g {rg} --gateway-name {ag} --priority 1002",
            checks=[
                self.check("routingRules[0].backendAddressPool.id", "{pool_id}"),
                self.check("routingRules[0].backendSettings.id", "{settings_id}"),
                self.check("routingRules[0].listener.id", "{listener_id}"),
            ]
        )
        self.cmd("network application-gateway routing-rule delete -n {routing_rule} -g {rg} --gateway-name {ag}")
        # default http listener has been associated with default rule
        self.cmd("network application-gateway frontend-port create -n {port2} -g {rg} --gateway-name {ag} --port 8082")
        self.cmd("network application-gateway http-listener create -n {http_listener} -g {rg} --gateway-name {ag} --frontend-port {port2} --frontend-ip appGatewayFrontendIP")
        # multiple pools are valid when redirection exsits
        self.cmd("network application-gateway address-pool create -n {pool} -g {rg} --gateway-name {ag}")
        self.cmd("network application-gateway frontend-port create -n rd-port -g {rg} --gateway-name {ag} --port 8084")
        self.cmd("network application-gateway http-listener create -n rd-listener -g {rg} --gateway-name {ag} --frontend-port rd-port --frontend-ip appGatewayFrontendIP")
        self.cmd("network application-gateway redirect-config create -n {redirect_config} -g {rg} --gateway-name {ag} --target-listener rd-listener --type permanent")
        self.cmd(
            "network application-gateway rule create -n {rule} -g {rg} --gateway-name {ag} --http-listener {http_listener} --redirect-config {redirect_config} --priority 1004",
            checks=[
                self.check("length(backendAddressPools)", 2),
                self.check("requestRoutingRules[0].backendAddressPool.id", "{pool_id}"),
                self.check("requestRoutingRules[0].backendHttpSettings.id", "{http_settings_id}"),
            ]
        )
        self.cmd("network application-gateway rule delete -n {rule} -g {rg} --gateway-name {ag}")

    @ResourceGroupPreparer(name_prefix='cli_test_ag_url_path_map')
    def test_network_ag_url_path_map(self, resource_group):
        self.kwargs.update({
            'ip': 'pip1',
            'ag': 'ag1',
            'name': 'mypathmap',
            'rulename': 'myurlrule',
            'rulename2': 'myurlrule2',
            'pool': 'mypool',
            'set': 'myruleset',
            'settings': 'http_settings',
            'rg': resource_group
        })
        self.cmd('network public-ip create -g {rg} -n {ip} --sku Standard')
        self.cmd('network application-gateway create -g {rg} -n {ag} --public-ip-address {ip} --sku Standard_v2 --priority 1001')
        self.cmd('network application-gateway wait -g {rg} -n {ag} --exists')

        self.cmd('network application-gateway http-listener create -g {rg} --gateway-name {ag} -n mylistener --no-wait --frontend-port appGatewayFrontendPort --host-name www.test.com')

        self.cmd('network application-gateway rewrite-rule set create -g {rg} --gateway-name {ag} -n {set}')
        self.cmd('network application-gateway address-pool create -g {rg} --gateway-name {ag} -n {pool} --no-wait')
        self.cmd('network application-gateway http-settings create -g {rg} --gateway-name {ag} -n {settings} --port 443 --protocol https')
        self.cmd('network application-gateway url-path-map create -g {rg} --gateway-name {ag} -n {name} --rule-name {rulename} --paths /mypath1/* --address-pool {pool} '
                 '--default-address-pool {pool} --http-settings {settings} --default-http-settings {settings} '
                 '--default-rewrite-rule-set {set} --rewrite-rule-set {set}')

        # test url-path-map list
        self.cmd('network application-gateway url-path-map list -g {rg} --gateway-name {ag}',
                 checks=[self.check('length(@)', 1)])

        # test url-path-map show
        self.cmd('network application-gateway url-path-map show -g {rg} --gateway-name {ag} -n {name}',
                 checks=[self.check('name', 'mypathmap')])

        self.cmd('network application-gateway url-path-map update -g {rg} --gateway-name {ag} -n {name} --default-rewrite-rule-set {set}')
        self.cmd('network application-gateway url-path-map rule create -g {rg} --gateway-name {ag} -n {rulename2} --path-map-name {name} '
                 '--paths /mypath122/* --address-pool {pool} --http-settings {settings} --rewrite-rule-set {set}')

        # test url-path-map rule delete
        self.cmd('network application-gateway url-path-map rule delete -g {rg} --gateway-name {ag} -n {rulename2} --path-map-name {name}')

        # test url-path-map delete
        self.cmd('network application-gateway url-path-map delete -g {rg} --gateway-name {ag} -n {name}')
        self.cmd('network application-gateway url-path-map list -g {rg} --gateway-name {ag}',
                 checks=[self.check('length(@)', 0)])


    @ResourceGroupPreparer(name_prefix='cli_test_ag_url_path_map_edge_case')
    def test_network_ag_url_path_map_edge_case(self, resource_group):
        self.kwargs.update({
            'ip': 'pip1',
            'ag': 'ag1',
            'name': 'mypathmap',
            'rulename': 'myurlrule',
            'rulename2': 'myurlrule2',
            'pool': 'mypool',
            'set': 'myruleset',
            'settings': 'http_settings',
            'redirect_config': 'myconfig',
            'rg': resource_group
        })
        self.cmd('network public-ip create -g {rg} -n {ip} --sku Standard')
        self.cmd(
            'network application-gateway create -g {rg} -n {ag} --public-ip-address {ip} --sku Standard_v2 --priority 1001')
        self.cmd('network application-gateway wait -g {rg} -n {ag} --exists')

        self.cmd(
            'network application-gateway http-listener create -g {rg} --gateway-name {ag} -n mylistener --no-wait --frontend-port appGatewayFrontendPort --host-name www.test.com')

        self.cmd('network application-gateway rewrite-rule set create -g {rg} --gateway-name {ag} -n {set}')
        self.cmd('network application-gateway redirect-config create -g {rg} --gateway-name {ag} -n {redirect_config} '
                 '--target-listener mylistener --type Permanent')
        self.cmd('network application-gateway address-pool create -g {rg} --gateway-name {ag} -n {pool} --no-wait')
        self.cmd(
            'network application-gateway http-settings create -g {rg} --gateway-name {ag} -n {settings} --port 443 --protocol https')
        self.cmd(
            'network application-gateway url-path-map create -g {rg} --gateway-name {ag} -n {name} --rule-name {rulename} --paths /mypath1/* '
            '--redirect-config {redirect_config} --default-redirect-config {redirect_config}')
        self.cmd(
            'network application-gateway url-path-map rule create -g {rg} --gateway-name {ag} -n {rulename2} --path-map-name {name} '
            '--paths /mypath122/* --address-pool {pool} --http-settings {settings}')
        with self.assertRaisesRegex(CLIError, "Cannot reference a BackendAddressPool when Redirect Configuration is specified."):
            self.cmd(
                'network application-gateway url-path-map rule create -g {rg} --gateway-name {ag} -n {rulename2} --path-map-name {name} '
                '--paths /mypath122/* --address-pool {pool} --http-settings {settings} --redirect-config {redirect_config}')

    @ResourceGroupPreparer(name_prefix='cli_test_ag_listener')
    def test_network_ag_listener(self, resource_group):
        self.kwargs.update({
            'appgw': 'appgw',
            'appgw_frontend_port': 'testFrontendPort01',
            'appgw_listener': 'testListener',
            'appgw_public_ip': 'testPublicIp',
            'appgw_rule_type': 'Basic',
            'res': 'application-gateway listener',
            'priority': 1001,
            'port1': 8080,
            'port2': 8081,
        })

        self.cmd('network public-ip create -g {rg} -n {appgw_public_ip} --sku Standard')

        self.cmd('network application-gateway create -g {rg} -n {appgw} '
                 '--public-ip-address {appgw_public_ip} --sku Standard_v2 '
                 '--priority {priority}')

        self.cmd('network application-gateway frontend-port create -g {rg} --gateway-name {appgw} '
                 '-n {appgw_frontend_port} --port {port1}')
        self.cmd('network application-gateway frontend-port create -g {rg} --gateway-name {appgw} '
                 '-n testFrontendPort02 --port {port2}')

        self.cmd('network {res} create -g {rg} --gateway-name {appgw} --frontend-port {appgw_frontend_port} '
                 '-n {appgw_listener} --frontend-ip appGatewayFrontendIP')

        self.cmd('network {res} show -g {rg} --gateway-name {appgw} -n {appgw_listener}',
                 checks=(self.check('name', '{appgw_listener}')))

        self.cmd('network {res} update -g {rg} --gateway-name {appgw} --frontend-port testFrontendPort02 -n {appgw_listener}')

        listener = self.cmd('network {res} show -g {rg} --gateway-name {appgw} -n {appgw_listener}').get_output_in_json()
        self.assertTrue(listener['frontendPort']['id'].endswith('testFrontendPort02'))

        self.cmd('network {res} list -g {rg} --gateway-name {appgw}',
                 checks=(self.check('length(@)', 1)))

        self.cmd('network {res} delete -g {rg} --gateway-name {appgw} -n {appgw_listener}')

        self.cmd('network {res} list -g {rg} --gateway-name {appgw}',
                 checks=(self.check('length(@)', 0)))

    @ResourceGroupPreparer(name_prefix='cli_test_ag_listener_with_host_names')
    @KeyVaultPreparer(name_prefix='cli-test-keyvault-', sku='premium', additional_params='--enable-rbac-authorization false')
    def test_network_ag_listener_with_host_names(self, resource_group):
        self.kwargs.update({
            'appgw': 'appgw',
            'appgw_frontend_port': 'testFrontendPort01',
            'appgw_listener': 'testListener',
            'appgw_public_ip': 'testPublicIp',
            'access_identity': 'id1',
            'priority': 1001,
            'cert': 'MyCertificate',
            'port': 8080,
            'ssl_cert_name': 'TestCertName',
        })

        # create a managed identity
        access_identity_result = self.cmd('identity create -g {rg} -n {access_identity}').get_output_in_json()
        self.kwargs.update({
            'access_identity_principal': access_identity_result['principalId']
        })

        self.cmd('keyvault set-policy -g {rg} -n {kv} '
                 '--object-id {access_identity_principal} --secret-permissions get list set')

        # create a certificate
        keyvault_cert_policy = self.cmd('az keyvault certificate get-default-policy').get_output_in_json()
        self.kwargs.update({
            'keyvault_cert_policy': keyvault_cert_policy
        })
        self.cmd('keyvault certificate create '
                 '--vault-name {kv} '
                 '--name {cert} '
                 '--policy "{keyvault_cert_policy}"')
        cert_result = self.cmd('keyvault certificate show --vault-name {kv} --name {cert}').get_output_in_json()
        self.kwargs.update({
            'secret_id': cert_result['sid']
        })

        self.cmd('network public-ip create -g {rg} -n {appgw_public_ip} --sku Standard')

        # create application-gateway with one_off_identity
        self.cmd('network application-gateway create '
                 '-g {rg} -n {appgw} '
                 '--sku Standard_v2 --public-ip-address {appgw_public_ip} '
                 '--identity {access_identity} '
                 '--frontend-port 1000 '
                 '--key-vault-secret-id {secret_id} '
                 '--ssl-certificate-name {ssl_cert_name} --priority {priority}', checks=[
            self.check('applicationGateway.sslCertificates[0].name', self.kwargs['ssl_cert_name']),
            self.check('applicationGateway.sslCertificates[0].properties.keyVaultSecretId', self.kwargs['secret_id']),
        ])
        self.cmd('network application-gateway frontend-port create -g {rg} --gateway-name {appgw} '
                 '-n {appgw_frontend_port} --port {port}')

        self.cmd('network application-gateway listener create -g {rg} --gateway-name {appgw} -n {appgw_listener} '
                 '--host-names "*.contoso.com" "www.microsoft.com" --frontend-port {appgw_frontend_port} '
                 '--frontend-ip appGatewayFrontendIP --ssl-cert {ssl_cert_name}')
        self.cmd('network application-gateway listener show -g {rg} --gateway-name {appgw} -n {appgw_listener}', checks=[
            self.check('length(hostNames)', 2),
            self.check('hostNames[0]', "*.contoso.com"),
            self.check('hostNames[1]', "www.microsoft.com")
        ])
        self.cmd('network application-gateway listener update -g {rg} --gateway-name {appgw} -n {appgw_listener} '
                 '--host-names "*.contoso.com" "www.bing.com"')
        self.cmd('network application-gateway listener show -g {rg} --gateway-name {appgw} -n {appgw_listener}', checks=[
            self.check('length(hostNames)', 2),
            self.check('hostNames[0]', "*.contoso.com"),
            self.check('hostNames[1]', "www.bing.com")
        ])
        self.cmd('network application-gateway listener list -g {rg} --gateway-name {appgw}', self.check('length(@)', 1))
        self.cmd('network application-gateway listener delete -g {rg} --gateway-name {appgw} -n {appgw_listener}')
        self.cmd('network application-gateway listener list -g {rg} --gateway-name {appgw}', self.check('length(@)', 0))

    @ResourceGroupPreparer(name_prefix='cli_test_ag_settings')
    def test_network_ag_settings(self, resource_group):
        self.kwargs.update({
            'appgw': 'appgw',
            'appgw_frontend_port1': 'testFrontendPort01',
            'appgw_frontend_port2': 'testFrontendPort02',
            'appgw_settings': 'testSettings',
            'appgw_public_ip': 'testPublicIp',
            'appgw_rule_type': 'Basic',
            'res': 'application-gateway settings',
            'priority': 1001,
            'port1': 8080,
            'port2': 8081
        })

        self.cmd('network public-ip create -g {rg} -n {appgw_public_ip} --sku Standard')

        self.cmd('network application-gateway create -g {rg} -n {appgw} '
                 '--public-ip-address {appgw_public_ip} --sku Standard_v2 '
                 '--priority {priority}')

        self.cmd('network application-gateway frontend-port create -g {rg} --gateway-name {appgw} '
                 '-n {appgw_frontend_port1} --port {port1}')
        self.cmd('network application-gateway frontend-port create -g {rg} --gateway-name {appgw} '
                 '-n {appgw_frontend_port2} --port {port2}')

        self.cmd('network {res} create -g {rg} --gateway-name {appgw} '
                 '--name {appgw_settings} --port {port1} ')

        self.cmd('network {res} show -g {rg} --gateway-name {appgw} -n {appgw_settings}',
                 checks=(self.check('name', '{appgw_settings}')))

        self.cmd('network {res} update -g {rg} --gateway-name {appgw} '
                 '--name {appgw_settings} --port {port2}')

        self.cmd('network {res} show -g {rg} --gateway-name {appgw} -n {appgw_settings}',
                 checks=(self.check('port', 8081)))

        self.cmd('network {res} list -g {rg} --gateway-name {appgw}',
                 checks=(self.check('length(@)', 1)))

        self.cmd('network {res} delete --gateway-name {appgw} --name {appgw_settings} --resource-group {rg}')

        self.cmd('network {res} list -g {rg} --gateway-name {appgw}',
                 checks=(self.check('length(@)', 0)))

    @ResourceGroupPreparer(name_prefix='cli_test_ag_routing_rule')
    def test_network_ag_routing_rule(self, resource_group):
        self.kwargs.update({
            'appgw': 'appgw',
            'appgw_frontend_port1': 'testFrontendPort01',
            'appgw_frontend_port2': 'testFrontendPort02',
            'appgw_settings': 'testSettings',
            'appgw_listener1': 'testListener01',
            'appgw_listener2': 'testListener02',
            'appgw_address_pool': 'testAddressPool',
            'appgw_routing_rule': 'testRule',
            'appgw_public_ip': 'testPublicIp',
            'appgw_rule_type': 'Basic',
            'res': 'application-gateway routing-rule',
            'priority': 1001,
            'port1': 8080,
            'port2': 8081
        })

        self.cmd('network public-ip create -g {rg} -n {appgw_public_ip} --sku Standard')

        self.cmd('network application-gateway create -g {rg} -n {appgw} '
                 '--public-ip-address {appgw_public_ip} --sku Standard_v2 '
                 '--priority {priority}')

        self.cmd('network application-gateway frontend-port create -g {rg} --gateway-name {appgw} '
                 '-n {appgw_frontend_port1} --port {port1}')
        self.cmd('network application-gateway frontend-port create -g {rg} --gateway-name {appgw} '
                 '-n {appgw_frontend_port2} --port {port2}')

        self.cmd('network application-gateway listener create -g {rg} --gateway-name {appgw} '
                 '--frontend-port {appgw_frontend_port1} -n {appgw_listener1} --frontend-ip appGatewayFrontendIP',
                 checks=(self.check('listeners[0].name', '{appgw_listener1}')))

        self.cmd('network application-gateway listener create -g {rg} --gateway-name {appgw} '
                 '--frontend-port {appgw_frontend_port2} -n {appgw_listener2} --frontend-ip appGatewayFrontendIP',
                 checks=(self.check('listeners[1].name', '{appgw_listener2}')))

        self.cmd('network application-gateway settings create -g {rg} --gateway-name {appgw} '
                 '--name {appgw_settings} --port {port1} ',
                 checks=(self.check('backendSettingsCollection[0].name', '{appgw_settings}')))
        self.cmd(
            'network application-gateway address-pool create -g {rg} --gateway-name {appgw} -n {appgw_address_pool} '
            '--servers 10.0.0.4 10.0.0.5')
        self.cmd('network {res} create -g {rg} --gateway-name {appgw} '
                 '--name {appgw_routing_rule} --listener {appgw_listener1} --rule-type {appgw_rule_type} '
                 '--address-pool {appgw_address_pool} --settings {appgw_settings} --priority 1002')

        self.cmd('network {res} show -g {rg} --gateway-name {appgw} -n {appgw_routing_rule}',
                 checks=(self.check('name', '{appgw_routing_rule}')))

        self.cmd('network {res} update -g {rg} --gateway-name {appgw} --name {appgw_routing_rule} '
                 '--listener {appgw_listener2} --rule-type {appgw_rule_type} '
                 '--address-pool {appgw_address_pool}')

        routing_rule = self.cmd('network {res} show -g {rg} --gateway-name {appgw} -n {appgw_routing_rule}').get_output_in_json()
        self.assertTrue(routing_rule['listener']['id'].endswith('testListener02'))

        self.cmd('network {res} list -g {rg} --gateway-name {appgw}',
                 checks=(self.check('length(@)', 1)))
        self.cmd('network {res} delete --gateway-name {appgw} --resource-group {rg} -n {appgw_routing_rule}')
        self.cmd('network {res} list -g {rg} --gateway-name {appgw}',
                 checks=(self.check('length(@)', 0)))


    @ResourceGroupPreparer(name_prefix='cli_test_ags_new_prop')
    def test_network_ags_enable_l4_client_ip_preservation(self, resource_group):
        self.kwargs.update({
            'public-ip-name': self.create_random_name(prefix='public',length=15),
            'vnet-name': self.create_random_name(prefix='vnet',length=15),
            'vnet-address': '10.10.0.0/16',
            'subnet-address': '10.10.0.0/24',
            'subnet-name': self.create_random_name(prefix='subnet',length=15),
            'gateway-name': self.create_random_name(prefix='gateway',length=15),
            'setting-name': self.create_random_name(prefix='setting',length=15),
            'port': 8080,
        })

        self.cmd('network public-ip create '
                 '--resource-group {rg} '
                 '--name {public-ip-name} '
                 '--sku Standard '
                 '--ip-tags FirstPartyUsage=/NonProd')

        self.cmd('network vnet create '
                 '--resource-group {rg} '
                 '--name {vnet-name} '
                 '--address-prefix {vnet-address}')

        self.cmd('network vnet subnet create '
                 '--resource-group {rg} '
                 '--name {subnet-name} '
                 '--vnet-name {vnet-name} '
                 '--address-prefix {subnet-address} '
                 '--default-outbound false')

        self.cmd('network application-gateway create '
                 '--resource-group {rg} '
                 '--name {gateway-name} '
                 '--sku Standard_v2 '
                 '--public-ip-address {public-ip-name} '
                 '--vnet-name {vnet-name} '
                 '--subnet {subnet-name} '
                 '--priority 1001')

        self.cmd('network application-gateway settings create '
                 '--resource-group {rg} '
                 '--name {setting-name} '
                 '--gateway-name {gateway-name} '
                 '--port {port}')

        self.cmd('network application-gateway settings show '
                 '--resource-group {rg} '
                 '--name {setting-name} '
                 '--gateway-name {gateway-name}',
                 checks=(self.check('enableL4ClientIpPreservation', False)))

        self.cmd('network application-gateway settings update '
                 '--resource-group {rg} '
                 '--name {setting-name} '
                 '--gateway-name {gateway-name} '
                 '--enable-l4-client-ip true',
                 checks=(self.check('enableL4ClientIpPreservation', True)))

        self.cmd('network application-gateway settings list '
                 '--resource-group {rg} '
                 '--gateway-name {gateway-name}',
                 checks = self.check('length(@)', 1))

        self.cmd('network application-gateway settings delete '
                 '--resource-group {rg} '
                 '--name {setting-name} '
                 '--gateway-name {gateway-name}')

        self.cmd('network application-gateway settings list '
                 '--resource-group {rg} '
                 '--gateway-name {gateway-name}',
                 checks=self.check('length(@)', 0))


    @ResourceGroupPreparer(name_prefix='cli_test_agp_new_prop')
    def test_network_ags_enable_probe_proxy_protocol_header(self, resource_group):
        self.kwargs.update({
            'public-ip-name': self.create_random_name(prefix='public',length=15),
            'vnet-name': self.create_random_name(prefix='vnet',length=15),
            'vnet-address': '10.10.0.0/16',
            'subnet-address': '10.10.0.0/24',
            'subnet-name': self.create_random_name(prefix='subnet',length=15),
            'gateway-name': self.create_random_name(prefix='gateway',length=15),
            'probe-name': self.create_random_name(prefix='probe',length=15),
        })

        self.cmd('network public-ip create '
                 '--resource-group {rg} '
                 '--name {public-ip-name} '
                 '--sku Standard '
                 '--ip-tags FirstPartyUsage=/NonProd')

        self.cmd('network vnet create '
                 '--resource-group {rg} '
                 '--name {vnet-name} '
                 '--address-prefix {vnet-address}')

        self.cmd('network vnet subnet create '
                 '--resource-group {rg} '
                 '--name {subnet-name} '
                 '--vnet-name {vnet-name} '
                 '--address-prefix {subnet-address} '
                 '--default-outbound false')

        self.cmd('network application-gateway create '
                 '--resource-group {rg} '
                 '--name {gateway-name} '
                 '--sku Standard_v2 '
                 '--public-ip-address {public-ip-name} '
                 '--vnet-name {vnet-name} '
                 '--subnet {subnet-name} '
                 '--priority 1001')

        self.cmd('network application-gateway probe create '
                 '--resource-group {rg} '
                 '--name {probe-name} '
                 '--gateway-name {gateway-name} '
                 '--protocol TCP')

        self.cmd('network application-gateway probe show '
                 '--resource-group {rg} '
                 '--name {probe-name} '
                 '--gateway-name {gateway-name}',
                 checks=(self.check('enableProbeProxyProtocolHeader', False)))

        self.cmd('network application-gateway probe update '
                 '--resource-group {rg} '
                 '--name {probe-name} '
                 '--gateway-name {gateway-name} '
                 '--enable-proxy-header true',
                 checks=(self.check('enableProbeProxyProtocolHeader', True)))

        self.cmd('network application-gateway probe list '
                 '--resource-group {rg} '
                 '--gateway-name {gateway-name}',
                 checks=self.check('length(@)', 1))

        self.cmd('network application-gateway probe delete '
                 '--resource-group {rg} '
                 '--name {probe-name} '
                 '--gateway-name {gateway-name}')

        self.cmd('network application-gateway probe list '
                 '--resource-group {rg} '
                 '--gateway-name {gateway-name}',
                 checks=self.check('length(@)', 0))


class NetworkAppGatewayRewriteRuleset(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_ag_rewrite_rulesets')
    def test_network_app_gateway_rewrite_rulesets(self, resource_group):

        self.kwargs.update({
            'gw': 'gw1',
            'ip': 'pip1',
            'set': 'ruleset1',
            'rule': 'rule1',
            'rule2': 'rule2',
            'rule3': 'rule3',
            'rule4': 'rule4',
            'var': 'http_req_Authorization'
        })
        self.cmd('network public-ip create -g {rg} -n {ip} --sku Standard')
        self.cmd('network application-gateway create -g {rg} -n {gw} --public-ip-address {ip} --sku Standard_v2 --priority 1001 --no-wait')
        self.cmd('network application-gateway wait -g {rg} -n {gw} --exists')

        # create ruleset
        self.cmd('network application-gateway rewrite-rule set create -g {rg} --gateway-name {gw} -n {set} --no-wait')
        self.cmd('network application-gateway rewrite-rule set show -g {rg} --gateway-name {gw} -n {set}')

        # manage rewrite rules
        self.cmd('network application-gateway rewrite-rule create -g {rg} --gateway-name {gw} --rule-set-name {set} -n {rule} --sequence 123 --request-headers foo=bar --response-headers cat=hat --no-wait')
        self.cmd('network application-gateway rewrite-rule update -g {rg} --gateway-name {gw} --rule-set-name {set} -n {rule} --sequence 321 --request-headers bar=foo --response-headers hat=cat --no-wait')
        self.cmd('network application-gateway rewrite-rule update -g {rg} --gateway-name {gw} --rule-set-name {set} -n {rule} --set ruleSequence=321 --remove actionSet.responseHeaderConfigurations 0 --no-wait')
        self.cmd('network application-gateway rewrite-rule show -g {rg} --gateway-name {gw} --rule-set-name {set} -n {rule}')
        self.cmd('network application-gateway rewrite-rule list -g {rg} --gateway-name {gw} --rule-set-name {set}')
        self.cmd('network application-gateway rewrite-rule list-request-headers')
        self.cmd('network application-gateway rewrite-rule list-response-headers')

        # manage rewrite rules with url configuration
        self.cmd('network application-gateway rewrite-rule create -g {rg} --gateway-name {gw} --rule-set-name {set} -n {rule2} '
                 '--sequence 123 --request-headers foo=bar --response-headers cat=hat '
                 '--modified-path "/def" --modified-query-string "a=b&c=d%20f"',
                 checks=[
                     self.check('actionSet.urlConfiguration.modifiedPath', '/def'),
                     self.check('actionSet.urlConfiguration.modifiedQueryString', 'a=b&c=d%20f'),
                     self.check('actionSet.urlConfiguration.reroute', False)
                 ])
        self.cmd('network application-gateway rewrite-rule update -g {rg} --gateway-name {gw} --rule-set-name {set} -n {rule2} '
                 '--sequence 321 --request-headers bar=foo --response-headers hat=cat '
                 '--modified-path "/def2" --modified-query-string "a=b&c=d%20f12" --enable-reroute',
                 checks=[
                     self.check('actionSet.urlConfiguration.modifiedPath', '/def2'),
                     self.check('actionSet.urlConfiguration.modifiedQueryString', 'a=b&c=d%20f12'),
                     self.check('actionSet.urlConfiguration.reroute', True)
                 ])
        self.cmd('network application-gateway rewrite-rule update -g {rg} --gateway-name {gw} --rule-set-name {set} -n {rule2} --set ruleSequence=321 --remove actionSet.responseHeaderConfigurations 0 --no-wait')
        self.cmd('network application-gateway rewrite-rule show -g {rg} --gateway-name {gw} --rule-set-name {set} -n {rule2}')

        # ISSUE#17373 create rewrite rule without
        self.cmd('network application-gateway rewrite-rule create -g {rg} --gateway-name {gw} --rule-set-name {set} -n {rule3} --sequence 123 --modified-path "/" --no-wait')

        # manage rewrite rules with response-header-configurations
        self.cmd('network application-gateway rewrite-rule create -g {rg} --gateway-name {gw} --rule-set-name {set} -n {rule4} '
                 '--sequence 123 --response-header-configurations [{{"header-name":Set-Cookie,"header-value":hat1,"header-value-matcher":{{"ignore-case":true,"negate":true,"pattern":"(https?)//.*azurewebsites.net(.*)$"}}}}] --request-headers foo=bar '
                 '--modified-path "/def" --modified-query-string "a=b&c=d%20f"',
                 checks=[
                     self.check('actionSet.responseHeaderConfigurations[0].headerName', 'Set-Cookie'),
                     self.check('actionSet.responseHeaderConfigurations[0].headerValue', 'hat1'),
                     self.check('actionSet.responseHeaderConfigurations[0].headerValueMatcher.ignoreCase', True),
                     self.check('actionSet.responseHeaderConfigurations[0].headerValueMatcher.negate', True),
                     self.check('actionSet.responseHeaderConfigurations[0].headerValueMatcher.pattern', "(https?)//.*azurewebsites.net(.*)$"),
                 ])
        self.cmd(
            'network application-gateway rewrite-rule update -g {rg} --gateway-name {gw} --rule-set-name {set} -n {rule4} '
            '--sequence 123 --response-header-configurations [{{"header-name":Set-Cookie,"header-value":hat2,"header-value-matcher":{{"ignore-case":true,"negate":false,"pattern":"(https?)//.*azurewebsites.net(.*)$"}}}}] --request-headers foo=bar '
            '--modified-path "/def" --modified-query-string "a=b&c=d%20f"',
            checks=[
                self.check('actionSet.responseHeaderConfigurations[0].headerName', 'Set-Cookie'),
                self.check('actionSet.responseHeaderConfigurations[0].headerValue', 'hat2'),
                self.check('actionSet.responseHeaderConfigurations[0].headerValueMatcher.ignoreCase', True),
                self.check('actionSet.responseHeaderConfigurations[0].headerValueMatcher.negate', False),
                self.check('actionSet.responseHeaderConfigurations[0].headerValueMatcher.pattern',
                           "(https?)//.*azurewebsites.net(.*)$"),
            ])

        # manage rewrite rule conditions
        self.cmd('network application-gateway rewrite-rule condition create -g {rg} --gateway-name {gw} --rule-set-name {set} --rule-name {rule} --variable {var} --pattern "^Bearer" --ignore-case false --negate --no-wait')
        self.cmd('network application-gateway rewrite-rule condition update -g {rg} --gateway-name {gw} --rule-set-name {set} --rule-name {rule} --variable {var} --pattern "^Bearers" --no-wait')
        self.cmd('network application-gateway rewrite-rule condition show -g {rg} --gateway-name {gw} --rule-set-name {set} --rule-name {rule} --variable {var}')
        self.cmd('network application-gateway rewrite-rule condition list -g {rg} --gateway-name {gw} --rule-set-name {set} --rule-name {rule}')
        self.cmd('network application-gateway rewrite-rule condition delete -g {rg} --gateway-name {gw} --rule-set-name {set} --rule-name {rule} --variable {var} --no-wait')
        self.cmd('network application-gateway rewrite-rule condition list -g {rg} --gateway-name {gw} --rule-set-name {set} --rule-name {rule}')
        self.cmd('network application-gateway rewrite-rule condition list-server-variables')

        self.cmd('network application-gateway rewrite-rule delete -g {rg} --gateway-name {gw} --rule-set-name {set} -n {rule} --no-wait')
        self.cmd('network application-gateway rewrite-rule list -g {rg} --gateway-name {gw} --rule-set-name {set}')

        self.cmd('network application-gateway rewrite-rule set delete -g {rg} --gateway-name {gw} -n {set} --no-wait')
        self.cmd('network application-gateway rewrite-rule set list -g {rg} --gateway-name {gw}')


class NetworkAppGatewayPublicIpScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_ag_public_ip')
    def test_network_app_gateway_with_public_ip(self, resource_group):

        self.kwargs['ip'] = 'publicip4'
        self.cmd('network application-gateway create -g {rg} -n test4 --subnet subnet1 --vnet-name vnet4 --vnet-address-prefix 10.0.0.1/16 --subnet-address-prefix 10.0.0.1/28 --public-ip-address {ip} --priority 1001', checks=[
            self.check("applicationGateway.frontendIPConfigurations[0].properties.publicIPAddress.contains(id, '{ip}')", True),
            self.check('applicationGateway.frontendIPConfigurations[0].properties.privateIPAllocationMethod', 'Dynamic')
        ])


class NetworkAppGatewayWafConfigScenarioTest20170301(ScenarioTest):

    @unittest.skip('SKU for this scenario is deprecated.')
    @AllowLargeResponse()
    @ResourceGroupPreparer(name_prefix='cli_test_app_gateway_waf_config')
    def test_network_app_gateway_waf_config(self, resource_group):

        self.kwargs.update({
            'ip': 'pip1',
            'ag': 'ag1'
        })
        self.cmd('network application-gateway create -g {rg} -n {ag} --subnet subnet1 --vnet-name vnet1 --public-ip-address {ip} --sku WAF_Medium --priority 1001 --no-wait')
        self.cmd('network application-gateway wait -g {rg} -n {ag} --exists')
        self.cmd('network application-gateway show -g {rg} -n {ag}', checks=[
            self.check("frontendIPConfigurations[0].publicIPAddress.contains(id, '{ip}')", True),
            self.check('frontendIPConfigurations[0].privateIPAllocationMethod', 'Dynamic')
        ])
        self.cmd('network application-gateway waf-config set -g {rg} --gateway-name {ag} --enabled true --firewall-mode prevention --rule-set-version 2.2.9 '
                 '--disabled-rule-groups crs_30_http_policy --disabled-rules 981175 981176 '
                 '--exclusion RequestHeaderNames StartsWith abc --exclusion RequestArgNames Equals def')
        self.cmd('network application-gateway waf-config show -g {rg} --gateway-name {ag}', checks=[
            self.check('enabled', True),
            self.check('firewallMode', 'Prevention'),
            self.check('length(disabledRuleGroups)', 2),
            self.check('length(disabledRuleGroups[1].rules)', 2),
            self.check('length(exclusions)', 2)
        ])
        # test list rule sets
        self.cmd('network application-gateway waf-config list-rule-sets --group *', checks=[
            self.check('length(@)', 6)
        ])

        self.cmd('network application-gateway waf-config list-dynamic-rule-sets -l westus',
                 self.check('type(@)', 'array'))


class NetworkAppGatewayWafPolicyScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_app_gateway_waf_policy_', location='westcentralus')
    def test_network_app_gateway_waf_policy_with_application_gateway(self, resource_group):
        self.kwargs.update({
            'waf': 'agp1',
            'custom-rule1': 'rule1',
            'custom-rule2': 'rule2',
            'ip1': 'pip1',
            'ag1': 'ag1',
            'ip2': 'pip2',
            'ag2': 'ag2',
            'rg': resource_group,
            'csr_grp1': 'REQUEST-931-APPLICATION-ATTACK-RFI',
            'csr_grp2': 'REQUEST-913-SCANNER-DETECTION'
        })

        # create a waf policy
        self.cmd('network application-gateway waf-policy create -g {rg} -n {waf}')
        self.cmd('network application-gateway waf-policy update -g {rg} -n {waf} --tags test=best',
                 checks=self.check('tags.test', 'best'))
        self.cmd('network application-gateway waf-policy show -g {rg} -n {waf}')
        self.cmd('network application-gateway waf-policy list -g {rg}',
                 checks=self.check('length(@)', 1))

        # test waf-policy delete
        self.cmd('network application-gateway waf-policy delete -g {rg} -n {waf}')
        self.cmd('network application-gateway waf-policy list -g {rg}',
                 checks=[
                     self.check('length(@)', 0)
                 ])
        self.cmd('network application-gateway waf-policy create -g {rg} -n {waf} --type OWASP --version 3.2')

        # add two custom rules of this waf-policy
        self.cmd('network application-gateway waf-policy custom-rule create -g {rg} '
                 '--policy-name {waf} -n {custom-rule1} '
                 '--priority 50 --action log --rule-type MatchRule '
                 '--match-conditions [{{"variables":[{{"variable_name":"RemoteAddr"}}],"operator":"IPMatch","values":["192.168.1.0/24","10.0.0.0/24"]}}]',
                 checks=self.check('priority', 50))
        self.cmd('network application-gateway waf-policy custom-rule create -g {rg} '
                 '--policy-name {waf} -n {custom-rule2} '
                 '--priority 100 --action log --rule-type MatchRule '
                 '--match-conditions [{{"variables":[{{"variable_name":"RemoteAddr"}}],"operator":"IPMatch","values":["192.168.1.0/24","10.0.0.0/24"]}}]')

        # test custom-rule list
        self.cmd('network application-gateway waf-policy custom-rule list -g {rg} '
                 '--policy-name {waf}',
                 checks=[
                     self.check('length(@)', 2)
                 ])

        # add two managed rule set to the managed rules of this waf-policy
        self.cmd('network application-gateway waf-policy managed-rule rule-set update -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.2 '
                 '--group-name {csr_grp1} --rule rule-id=931120 --rule rule-id=931130')
        self.cmd('network application-gateway waf-policy managed-rule rule-set update -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.2 '
                 '--group-name {csr_grp2} --rule rule-id=913100')

        # update some policy settings of this waf-policy
        self.cmd('network application-gateway waf-policy policy-setting update -g {rg} --policy-name {waf} '
                 '--state Enabled --file-upload-limit-in-mb 64 --mode Prevention')

        # test waf-policy policy-setting list
        self.cmd('network application-gateway waf-policy policy-setting list -g {rg} --policy-name {waf}', checks=[
            self.check("type(@)", "object")
        ])

        self.cmd('network application-gateway waf-policy managed-rule rule-set add -g {rg} --policy-name {waf} '
                 '--type Microsoft_BotManagerRuleSet --version 1.0',
                 checks=[
                     self.check('managedRules.managedRuleSets[1].ruleSetType', 'Microsoft_BotManagerRuleSet'),
                     self.check('managedRules.managedRuleSets[1].ruleSetVersion', '1.0')
                 ])
        
        self.cmd('network application-gateway waf-policy managed-rule rule-set update -g {rg} --policy-name {waf} '
                 '--type Microsoft_BotManagerRuleSet --version 1.1',
                 checks=[
                     self.check('managedRules.managedRuleSets[1].ruleSetType', 'Microsoft_BotManagerRuleSet'),
                     self.check('managedRules.managedRuleSets[1].ruleSetVersion', '1.1')
                 ])

        # add one exclusion rule to the managed rules of this waf-policy
        self.cmd('network application-gateway waf-policy managed-rule exclusion add -g {rg} --policy-name {waf} '
                 '--match-variable "RequestHeaderNames" --selector-match-operator "StartsWith" --selector "Bing"')

        self.cmd('network application-gateway waf-policy show -g {rg} -n {waf}', checks=[
            self.check('customRules | length(@)', 2),
            self.check('customRules[0].priority', 50),
            self.check('customRules[1].priority', 100),
            self.check('managedRules.managedRuleSets[0].ruleSetType', 'OWASP'),
            self.check('managedRules.managedRuleSets[0].ruleSetVersion', '3.2'),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].rules | length(@)', 2),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].ruleGroupName', self.kwargs['csr_grp1']),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].rules[0].ruleId', '931120'),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[1].ruleGroupName', self.kwargs['csr_grp2']),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[1].rules[0].ruleId', '913100'),
            self.check('managedRules.managedRuleSets[1].ruleSetType', 'Microsoft_BotManagerRuleSet'),
            self.check('managedRules.managedRuleSets[1].ruleSetVersion', '1.1'),
            self.check('policySettings.fileUploadLimitInMb', 64),
            self.check('policySettings.maxRequestBodySizeInKb', 128),
            self.check('policySettings.mode', 'Prevention'),
            self.check('policySettings.requestBodyCheck', False),
            self.check('policySettings.state', 'Enabled')
        ])

        # prepare two IPs
        self.cmd('network public-ip create -g {rg} -n {ip1} --sku standard --ip-tags FirstPartyUsage=/NonProd')
        self.cmd('network public-ip create -g {rg} -n {ip2} --sku standard --ip-tags FirstPartyUsage=/NonProd')

        self.cmd('network vnet create -g {rg} -n vnet1 --address-prefix 10.0.0.0/16')
        self.cmd('network vnet subnet create -g {rg} --vnet-name vnet1 -n subnet1 --address-prefix 10.0.0.0/24 --default-outbound false')

        self.cmd('network vnet create -g {rg} -n vnet2 --address-prefix 10.0.0.0/16')
        self.cmd('network vnet subnet create -g {rg} --vnet-name vnet2 -n subnet2 --address-prefix 10.0.0.0/24 --default-outbound false')

        # create two application gateways and assign with the same waf-policy
        self.cmd('network application-gateway create -g {rg} -n {ag1} --subnet subnet1 --vnet-name vnet1 '
                 '--public-ip-address {ip1} --sku WAF_v2 --waf-policy {waf} --priority 1001')
        self.cmd('network application-gateway create -g {rg} -n {ag2} --subnet subnet2 --vnet-name vnet2 '
                 '--public-ip-address {ip2} --sku WAF_v2 --waf-policy {waf} --priority 1001')

        self.cmd('network application-gateway show -g {rg} -n {ag1}',
                 checks=self.check("firewallPolicy.contains(id, '{waf}')", True))
        self.cmd('network application-gateway show -g {rg} -n {ag2}',
                 checks=self.check("firewallPolicy.contains(id, '{waf}')", True))

        # test assigned application-gateways
        self.cmd('network application-gateway waf-policy show -g {rg} -n {waf}', checks=[
            self.check('applicationGateways | length(@)', 2),
            self.check("contains(applicationGateways[0].id, '{ag1}')", True),
            self.check("contains(applicationGateways[1].id, '{ag2}')", True)
        ])

        # test custom-rule delete
        self.cmd('network application-gateway waf-policy custom-rule delete -g {rg} '
                 '--policy-name {waf} -n {custom-rule2}')
        self.cmd('network application-gateway waf-policy custom-rule list -g {rg} '
                 '--policy-name {waf}',
                 checks=[
                     self.check('length(@)', 1)
                 ])

    @ResourceGroupPreparer(name_prefix='cli_test_app_gateway_waf_custom_rule_')
    def test_network_app_gateway_waf_custom_rule(self, resource_group):
        from azure.cli.core.azclierror import ArgumentUsageError
        self.kwargs.update({
            'waf': 'agp1',
            'rule': 'rule1',
            'ip': 'pip1',
            'ag': 'ag1',
            'rg': resource_group,
            'custom-rule1':'custom-rule1'
        })

        # create a waf-policy with empty custom rule
        self.cmd('network application-gateway waf-policy create -g {rg} -n {waf}')
        self.cmd('network application-gateway waf-policy show -g {rg} -n {waf}', checks=[
            self.check('customRules | length(@)', 0)
        ])

        # create a custom rule
        self.cmd('network application-gateway waf-policy custom-rule create -g {rg} '
                 '--policy-name {waf} -n {rule} '
                 '--priority 50 --action LOG --rule-type MatchRule '
                 '--match-conditions [{{"variables":[{{"variable_name":"RemoteAddr"}}],"operator":"IPMatch","values":["192.168.1.0/24","10.0.0.0/24"]}}]',
                 checks=[
                     self.check('priority', 50),
                     self.check('ruleType', 'MatchRule'),
                     self.check('action', 'Log'),
                     self.check('matchConditions | length(@)', 1),
                     self.check("state", "Enabled")
                 ])
        self.cmd('network application-gateway waf-policy show -g {rg} -n {waf}', checks=[
            self.check('customRules | length(@)', 1)
        ])
        self.cmd('network application-gateway waf-policy custom-rule show -g {rg} '
                 '--policy-name {waf} -n {rule}',
                 checks=[
                     self.check('priority', 50),
                     self.check('ruleType', 'MatchRule'),
                     self.check('action', 'Log'),
                     self.check('matchConditions | length(@)', 1)
                 ])
        # validate match condition
        with self.assertRaisesRegex(ArgumentUsageError, 'requires --values'):
            self.cmd("network application-gateway waf-policy custom-rule match-condition add -g {rg} "
                     "--policy-name {waf} -n {rule} "
                     "--match-variables RequestHeaders.value --operator Contains --transform lowercase")

        # add match condition to the previous created custom rule
        self.cmd('network application-gateway waf-policy custom-rule match-condition add -g {rg} '
                 '--policy-name {waf} -n {rule} '
                 '--match-variables RequestHeaders.value --operator contains --values foo boo --transform lowercase')
        self.cmd('network application-gateway waf-policy custom-rule show -g {rg} '
                 '--policy-name {waf} -n {rule}',
                 checks=[
                     self.check('priority', 50),
                     self.check('ruleType', 'MatchRule'),
                     self.check('action', 'Log'),
                     self.check('matchConditions | length(@)', 2)
                 ])

        # update one of properties
        self.cmd('network application-gateway waf-policy custom-rule update -g {rg} --state disabled '
                 '--policy-name {waf} -n {rule} '
                 '--priority 75',
                 checks=[
                     self.check('priority', 75),
                     self.check("state", "Disabled")
                 ])

        # add another match condition to the same custom rule
        self.cmd('network application-gateway waf-policy custom-rule match-condition add -g {rg} '
                 '--policy-name {waf} -n {rule} '
                 '--match-variables RequestHeaders.value --operator contains '
                 '--values remove this --transform uppercase')
        self.cmd('network application-gateway waf-policy custom-rule show -g {rg} '
                 '--policy-name {waf} -n {rule}',
                 checks=[
                     self.check('priority', 75),
                     self.check('ruleType', 'MatchRule'),
                     self.check('action', 'Log'),
                     self.check('matchConditions | length(@)', 3)
                 ])
        self.cmd('network application-gateway waf-policy custom-rule match-condition list -n {rule} -g {rg} '
                 '--policy-name {waf}',
                 checks=[
                     self.check('length(@)', 3)
                 ])

        # remove one of match condition of custom rule
        self.cmd('network application-gateway waf-policy custom-rule match-condition remove -g {rg} '
                 '--policy-name {waf} -n {rule} '
                 '--index 0')
        self.cmd('network application-gateway waf-policy custom-rule show -g {rg} '
                 '--policy-name {waf} -n {rule}',
                 checks=[
                     self.check('priority', 75),
                     self.check('ruleType', 'MatchRule'),
                     self.check('action', 'Log'),
                     self.check('matchConditions | length(@)', 2)
                 ])

    @ResourceGroupPreparer(name_prefix='cli_test_app_gateway_waf_custom_rule_v2_')
    def test_network_app_gateway_waf_custom_rule_v2(self, resource_group):
        self.kwargs.update({
            'waf': 'agp1',
            'rule': 'rule1',
            'rule2': 'rule2',
            'rule3': 'rule3',
            'ip': 'pip1',
            'ag': 'ag1',
            'custom-rule1': 'custom-rule1'
        })
        # create a waf-policy with empty custom rule
        self.cmd('network application-gateway waf-policy create -g {rg} -n {waf}')

        self.cmd('network application-gateway waf-policy managed-rule rule-set update -g {rg} --policy-name {waf} --type OWASP --version 3.2 --group-name "REQUEST-931-APPLICATION-ATTACK-RFI" --rule rule-id=931120 state=Enabled action=Log --rule rule-id=931130 state=Disabled action=AnomalyScoring')
        self.cmd('network application-gateway waf-policy managed-rule exclusion rule-set add -g {rg} --policy-name {waf} --match-variable RequestArgNames --selector-match-operator StartsWith --selector hello --type OWASP --version 3.2 --group-name REQUEST-930-APPLICATION-ATTACK-LFI --rule-ids 930120 ')
        self.cmd('network application-gateway waf-policy managed-rule exclusion rule-set add -g {rg} --policy-name {waf} --match-variable RequestArgNames --selector-match-operator StartsWith --selector hello --type OWASP --version 3.2 --group-name REQUEST-932-APPLICATION-ATTACK-RCE')
        self.cmd('network application-gateway waf-policy managed-rule exclusion rule-set add -g {rg} --policy-name {waf} --match-variable RequestArgNames --selector-match-operator EndsWith --selector hello --type OWASP --version 3.2')
        self.cmd('network application-gateway waf-policy managed-rule exclusion add -g {rg} --policy-name {waf} --match-variable RequestArgNames --selector-match-operator StartsWith --selector test')
        self.cmd('network application-gateway waf-policy managed-rule exclusion add -g {rg} --policy-name {waf} --match-variable RequestArgValues --selector-match-operator StartsWith --selector test')
        self.cmd('network application-gateway waf-policy policy-setting update -g {rg} --policy-name {waf} '
                 '--log-scrubbing-state Enabled --scrubbing-rules [{{"state":"Enabled","match-variable":"RequestArgNames","selector-match-operator":"Equals","selector":"test"}},{{"state":"Enabled","match-variable":"RequestIPAddress","selector-match-operator":"EqualsAny","selector":null}}]')

        # create a custom rule
        self.cmd('network application-gateway waf-policy custom-rule create -g {rg} '
                 '--policy-name {waf} -n {rule} '
                 '--priority 1 '
                 '--action Block '
                 '--rule-type MatchRule '
                 '--match-conditions [{{"variables":[{{"variable_name":"RemoteAddr"}}],"operator":"IPMatch","values":["192.168.2.0/24","10.0.2.0/24"]}}]')
        self.cmd('network application-gateway waf-policy custom-rule create -g {rg} '
                 '--policy-name {waf} -n {rule2} '
                 '--priority 2 '
                 '--action Block '
                 '--rule-type MatchRule '
                 '--match-conditions [{{"variables":[{{"variable_name":"RemoteAddr"}}],"operator":"IPMatch","values":["192.168.2.0/24","10.0.2.0/24"]}}]')

        self.cmd('network application-gateway waf-policy custom-rule match-condition add -g {rg} '
                 '--policy-name {waf} -n {rule} --match-variables RemoteAddr '
                 '--operator IPMatch --values "192.168.1.0/24" "10.0.0.0/24" --negate false')
        self.cmd('network application-gateway waf-policy custom-rule match-condition add -g {rg} '
                 '--policy-name {waf} -n {rule2} --negate false '
                 '--match-variables RemoteAddr --operator IPMatch --values "192.168.1.0/24" ')
        self.cmd('network application-gateway waf-policy custom-rule match-condition add -g {rg} '
                 '--policy-name {waf} -n {rule2} '
                 '--match-variables RequestHeaders.UserAgent --operator Contains --values "Windows"')

        self.cmd('network application-gateway waf-policy custom-rule create -g {rg} '
                 '--policy-name {waf} -n {rule3} '
                 '--priority 3 '
                 '--action Block '
                 '--rule-type RateLimitRule '
                 '--rate-limit-duration FiveMins '
                 '--rate-limit-threshold 15 '
                 '--group-by-user-session [{{group-by-variables:[{{variable-name:"GeoLocation"}}]}}] '
                 '--match-conditions [{{"variables":[{{"variable_name":"RemoteAddr"}}],"operator":"IPMatch","values":["192.168.2.0/24","10.0.2.0/24"]}}]',
                 checks=[self.check('name', '{rule3}'),
                         self.check('groupByUserSession[0].groupByVariables[0].variableName', 'GeoLocation'),
                         self.check('rateLimitDuration', 'FiveMins'),
                         self.check('rateLimitThreshold', '15')])

        self.cmd('network application-gateway waf-policy custom-rule update -g {rg} '
                 '--policy-name {waf} -n {rule3} '
                 '--rate-limit-duration OneMin '
                 '--rate-limit-threshold 10 '
                 '--group-by-user-session [{{group-by-variables:[{{variable-name:"ClientAddr"}}]}}]',
                 checks=[self.check('name', '{rule3}'),
                         self.check('groupByUserSession[0].groupByVariables[0].variableName', 'ClientAddr'),
                         self.check('rateLimitDuration', 'OneMin'),
                         self.check('rateLimitThreshold', '10')])
        self.cmd('network application-gateway waf-policy custom-rule match-condition add -g {rg} '
                 '--policy-name {waf} -n {rule3} --negate true '
                 '--match-variables RemoteAddr --operator IPMatch --values "192.168.1.0/24" "10.0.0.0/24"')
        
        self.cmd('network application-gateway waf-policy custom-rule create -g {rg} '
                 '--policy-name {waf} --name ClientIPRateLimitRule '
                 '--action Block  --priority 90 --rule-type RateLimitRule --rate-limit-threshold 100 '
                 '--group-by-user-session [{{group-by-variables:[{{variable-name:"ClientAddrXffHeader"}}]}}] '
                 '--match-conditions [{{"variables":[{{"variable_name":"RequestHeaders"}}],"operator":"IPMatch","values":["198.51.100.0/24"]}}]')

    @ResourceGroupPreparer(name_prefix='cli_test_app_gateway_waf_policy_setting_')
    def test_network_app_gateway_waf_policy_setting(self, resource_group):
        self.kwargs.update({
            'waf': 'agp1',
            'ag': 'ag1',
            'rg': resource_group,
        })

        # check default policy setting values
        self.cmd('network application-gateway waf-policy create -g {rg} -n {waf}', checks=[
            self.check('policySettings.fileUploadLimitInMb', 100),
            self.check('policySettings.maxRequestBodySizeInKb', 128),
            self.check('policySettings.mode', 'Detection'),
            self.check('policySettings.requestBodyCheck', True),
            self.check('policySettings.state', 'Disabled')
        ])
        self.cmd('network application-gateway waf-policy managed-rule rule-set update -g {rg} --policy-name {waf} --type OWASP --version 3.2 --group-name "REQUEST-931-APPLICATION-ATTACK-RFI" --rule rule-id=931120 state=Enabled action=Log --rule rule-id=931130 state=Disabled action=AnomalyScoring')

        # randomly update some properties
        self.cmd('network application-gateway waf-policy policy-setting update -g {rg} --policy-name {waf} '
                 '--state Enabled --file-upload-limit-in-mb 64 --mode Prevention --js-cookie-exp-time 100',
                 checks=[
                     self.check('policySettings.fileUploadLimitInMb', 64),
                     self.check('policySettings.maxRequestBodySizeInKb', 128),
                     self.check('policySettings.mode', 'Prevention'),
                     self.check('policySettings.requestBodyCheck', False),
                     self.check('policySettings.state', 'Enabled'),
                     self.check('policySettings.jsChallengeCookieExpirationInMins', 100)
                 ])

    @ResourceGroupPreparer(name_prefix='cli_test_app_gateway_waf_policy_setting_v2_')
    def test_network_app_gateway_waf_policy_setting_v2(self, resource_group):
        self.kwargs.update({
            'waf': 'agp1',
            'ag': 'ag1',
            'rg': resource_group,
        })

        # check default policy setting values
        self.cmd('network application-gateway waf-policy create -g {rg} -n {waf}', checks=[
            self.check('policySettings.fileUploadLimitInMb', 100),
            self.check('policySettings.maxRequestBodySizeInKb', 128),
            self.check('policySettings.mode', 'Detection'),
            self.check('policySettings.requestBodyCheck', True),
            self.check('policySettings.state', 'Disabled')
        ])
        self.cmd('network application-gateway waf-policy managed-rule rule-set update -g {rg} --policy-name {waf} --type OWASP --version 3.2 --group-name "REQUEST-931-APPLICATION-ATTACK-RFI" --rule rule-id=931120 state=Enabled action=Log --rule rule-id=931130 state=Disabled action=AnomalyScoring')
        # randomly update some properties
        self.cmd('network application-gateway waf-policy policy-setting update -g {rg} --policy-name {waf} '
                 '--request-body-inspect-limit-in-kb 64 --file-upload-enforcement True --request-body-enforcement False '
                 '--log-scrubbing-state Enabled --scrubbing-rules [{{"state":"Enabled","match-variable":"RequestArgNames","selector-match-operator":"Equals","selector":"test"}},{{"state":"Enabled","match-variable":"RequestIPAddress","selector-match-operator":"EqualsAny","selector":null}}]',
                 checks=[
                     self.check('policySettings.requestBodyInspectLimitInKB', 64),
                     self.check('policySettings.requestBodyEnforcement', False),
                     self.check('policySettings.fileUploadEnforcement', True),
                     self.check('policySettings.logScrubbing.scrubbingRules | length(@)', 2),
                     self.check('policySettings.logScrubbing.state', 'Enabled')
                 ])

    @ResourceGroupPreparer(name_prefix='cli_test_app_gateway_waf_policy_managed_rules_')
    def test_network_app_gateway_waf_policy_managed_rules(self, resource_group):
        self.kwargs.update({
            'waf': 'agp1',
            'ip': 'pip1',
            'ag': 'ag1',
            'rg': resource_group,
            'csr_grp1': 'REQUEST-921-PROTOCOL-ATTACK',
            'csr_grp2': 'REQUEST-913-SCANNER-DETECTION',
            'csr_grp3': 'REQUEST-931-APPLICATION-ATTACK-RFI'
        })

        # create a waf-policy with default type and version
        self.cmd('network application-gateway waf-policy create -g {rg} -n {waf}', checks=[
            self.check('name', '{waf}'),
            self.check('managedRules.managedRuleSets[0].ruleSetType', 'Microsoft_DefaultRuleSet'),
            self.check('managedRules.managedRuleSets[0].ruleSetVersion', '2.1'),
        ])
        self.cmd('network application-gateway waf-policy delete -g {rg} -n {waf}')

        # create a waf-policy
        self.cmd('network application-gateway waf-policy create -g {rg} -n {waf} --version 3.0 --type OWASP')

        # case 1: Initialize(add) managed rule set
        self.cmd('network application-gateway waf-policy managed-rule rule-set add -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.0 '
                 '--group-name {csr_grp1} --rule rule-id=921100 --rule rule-id=921110 sensitivity=low')
        self.cmd('network application-gateway waf-policy show -g {rg} -n {waf}', checks=[
            self.check('managedRules.managedRuleSets[0].ruleSetType', 'OWASP'),
            self.check('managedRules.managedRuleSets[0].ruleSetVersion', '3.0'),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].rules | length(@)', 2),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].ruleGroupName', self.kwargs['csr_grp1']),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].rules[0].ruleId', '921100'),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].rules[1].sensitivity', 'Low')
        ])

        # case 2: Append(add) another managed rule set to same rule group
        self.cmd('network application-gateway waf-policy managed-rule rule-set add -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.0 '
                 '--group-name {csr_grp1} --rule rule-id=921150 sensitivity=medium')
        self.cmd('network application-gateway waf-policy managed-rule rule-set list -g {rg} --policy-name {waf}',
                 checks=[
                     self.check('managedRuleSets[0].ruleSetType', 'OWASP'),
                     self.check('managedRuleSets[0].ruleSetVersion', '3.0'),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].rules | length(@)', 3),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].ruleGroupName', self.kwargs['csr_grp1']),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].rules[2].ruleId', '921150'),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].rules[2].sensitivity', 'Medium')
                 ])

        # case 3: Add another managed rule set of different rule group
        self.cmd('network application-gateway waf-policy managed-rule rule-set add -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.0 '
                 '--group-name {csr_grp2} --rule rule-id=913100')
        self.cmd('network application-gateway waf-policy managed-rule rule-set list -g {rg} --policy-name {waf}',
                 checks=[
                     self.check('managedRuleSets[0].ruleSetType', 'OWASP'),
                     self.check('managedRuleSets[0].ruleSetVersion', '3.0'),
                     self.check('managedRuleSets[0].ruleGroupOverrides[1].rules | length(@)', 1),
                     self.check('managedRuleSets[0].ruleGroupOverrides[1].ruleGroupName', self.kwargs['csr_grp2']),
                     self.check('managedRuleSets[0].ruleGroupOverrides[1].rules[0].ruleId', '913100')
                 ])

        # case 4: override(update) existing managed rule set
        self.cmd('network application-gateway waf-policy managed-rule rule-set update -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.0 '
                 '--group-name {csr_grp1} --rule rule-id=921100 --rule rule-id=921150')
        self.cmd('network application-gateway waf-policy managed-rule rule-set list -g {rg} --policy-name {waf}',
                 checks=[
                     self.check('managedRuleSets[0].ruleSetType', 'OWASP'),
                     self.check('managedRuleSets[0].ruleSetVersion', '3.0'),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].rules | length(@)', 2),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].ruleGroupName', self.kwargs['csr_grp1']),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].rules[0].ruleId', '921100'),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].rules[1].ruleId', '921150'),
                 ])

        # case 5: clear manage rule set by group {csr_grp1} and only {csr_grp2} left
        self.cmd('network application-gateway waf-policy managed-rule rule-set remove -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.1 '
                 '--group-name {csr_grp1} ')
        self.cmd('network application-gateway waf-policy managed-rule rule-set list -g {rg} --policy-name {waf}', checks=[
            self.check('managedRuleSets[0].ruleGroupOverrides | length(@)', 1),
            self.check('managedRuleSets[0].ruleGroupOverrides[0].rules | length(@)', 1),
            self.check('managedRuleSets[0].ruleGroupOverrides[0].ruleGroupName', self.kwargs['csr_grp2']),
            self.check('managedRuleSets[0].ruleGroupOverrides[0].rules[0].ruleId', '913100'),
        ])

        # case 6: change managed rules of OWASP from 3.1 to 3.0
        self.cmd('network application-gateway waf-policy managed-rule rule-set update -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.1')

        self.cmd('network application-gateway waf-policy managed-rule rule-set list -g {rg} --policy-name {waf}',
                 checks=[
                     self.check('managedRuleSets[0].ruleSetType', 'OWASP'),
                     self.check('managedRuleSets[0].ruleSetVersion', '3.1'),
                     self.check('managedRuleSets[0].ruleGroupOverrides | length(@)', 0)
                 ])

        # case 7: override existing rules with one rule for OWASP 3.1
        self.cmd('network application-gateway waf-policy managed-rule rule-set update -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.1 '
                 '--group-name REQUEST-911-METHOD-ENFORCEMENT '
                 '--rule rule-id=911100')
        self.cmd('network application-gateway waf-policy managed-rule rule-set list -g {rg} --policy-name {waf}', checks=[
            self.check('managedRuleSets[0].ruleSetType', 'OWASP'),
            self.check('managedRuleSets[0].ruleSetVersion', '3.1'),
            self.check('managedRuleSets[0].ruleGroupOverrides | length(@)', 1),
            self.check('managedRuleSets[0].ruleGroupOverrides[0].rules | length(@)', 1),
            self.check('managedRuleSets[0].ruleGroupOverrides[0].rules[0].ruleId', '911100')
        ])

        # case 8: validate per rule action
        self.cmd('network application-gateway waf-policy managed-rule rule-set update -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.2')
        self.cmd('network application-gateway waf-policy managed-rule rule-set update -g {rg} --policy-name {waf} '
                 '--type Microsoft_DefaultRuleSet --version 2.1')

        self.cmd('network application-gateway waf-policy managed-rule rule-set add -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.2 '
                 '--group-name {csr_grp3} '
                 '--rule rule-id=931120 state=Enabled action=Log '
                 '--rule rule-id=931130 state=Disabled action=AnomalyScoring')
        self.cmd('network application-gateway waf-policy show -g {rg} -n {waf}', checks=[
            self.check('managedRules.managedRuleSets[0].ruleSetType', 'OWASP'),
            self.check('managedRules.managedRuleSets[0].ruleSetVersion', '3.2'),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].rules | length(@)', 2),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].ruleGroupName', self.kwargs['csr_grp3']),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].rules[0].ruleId', '931120'),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].rules[0].state', 'Enabled'),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].rules[0].action', 'Log'),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].rules[1].ruleId', '931130'),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].rules[1].state', 'Disabled'),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].rules[1].action', 'AnomalyScoring')
        ])

    @ResourceGroupPreparer(name_prefix='cli_test_app_gateway_waf_policy_managed_rules_')
    def test_network_app_gateway_waf_policy_with_version_and_type(self, resource_group):
        self.kwargs.update({
            'waf': 'agp1',
            'ip': 'pip1',
            'ag': 'ag1',
            'rg': resource_group,
            'csr_grp1': 'REQUEST-921-PROTOCOL-ATTACK',
            'csr_grp2': 'REQUEST-913-SCANNER-DETECTION'
        })
        self.cmd('network application-gateway waf-policy create -g {rg} -n {waf} --version 3.1 --type OWASP')

        # case 1: Initialize(add) managed rule set
        self.cmd('network application-gateway waf-policy managed-rule rule-set add -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.1 '
                 '--group-name {csr_grp1} --rule rule-id=921120 --rule rule-id=921110')
        self.cmd('network application-gateway waf-policy show -g {rg} -n {waf}', checks=[
            self.check('managedRules.managedRuleSets[0].ruleSetType', 'OWASP'),
            self.check('managedRules.managedRuleSets[0].ruleSetVersion', '3.1'),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].rules | length(@)', 2),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].ruleGroupName', self.kwargs['csr_grp1']),
            self.check('managedRules.managedRuleSets[0].ruleGroupOverrides[0].rules[0].ruleId', '921120')
        ])

        # case 2: Append(add) another managed rule set to same rule group
        self.cmd('network application-gateway waf-policy managed-rule rule-set add -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.1 '
                 '--group-name {csr_grp1} --rule rule-id=921150')
        self.cmd('network application-gateway waf-policy managed-rule rule-set list -g {rg} --policy-name {waf}',
                 checks=[
                     self.check('managedRuleSets[0].ruleSetType', 'OWASP'),
                     self.check('managedRuleSets[0].ruleSetVersion', '3.1'),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].rules | length(@)', 3),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].ruleGroupName', self.kwargs['csr_grp1']),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].rules[2].ruleId', '921150')
                 ])

        # # case 3: Add another managed rule set of different rule group
        self.cmd('network application-gateway waf-policy managed-rule rule-set add -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.1 '
                 '--group-name {csr_grp2} --rule rule-id=913100')
        self.cmd('network application-gateway waf-policy managed-rule rule-set list -g {rg} --policy-name {waf}',
                 checks=[
                     self.check('managedRuleSets[0].ruleSetType', 'OWASP'),
                     self.check('managedRuleSets[0].ruleSetVersion', '3.1'),
                     self.check('managedRuleSets[0].ruleGroupOverrides[1].rules | length(@)', 1),
                     self.check('managedRuleSets[0].ruleGroupOverrides[1].ruleGroupName', self.kwargs['csr_grp2']),
                     self.check('managedRuleSets[0].ruleGroupOverrides[1].rules[0].ruleId', '913100')
                 ])

        # case 4: override(update) existing managed rule set
        self.cmd('network application-gateway waf-policy managed-rule rule-set update -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.1 '
                 '--group-name {csr_grp1} --rule rule-id=921130 --rule rule-id=921140')
        self.cmd('network application-gateway waf-policy managed-rule rule-set list -g {rg} --policy-name {waf}',
                 checks=[
                     self.check('managedRuleSets[0].ruleSetType', 'OWASP'),
                     self.check('managedRuleSets[0].ruleSetVersion', '3.1'),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].rules | length(@)', 2),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].ruleGroupName', self.kwargs['csr_grp1']),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].rules[0].ruleId', '921130'),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].rules[1].ruleId', '921140')
                 ])

        # # case 5: clear manage rule set by group {csr_grp1}
        self.cmd('network application-gateway waf-policy managed-rule rule-set remove -g {rg} --policy-name {waf} '
                 '--type OWASP --version 3.1 '
                 '--group-name {csr_grp1} ')
        self.cmd('network application-gateway waf-policy managed-rule rule-set list -g {rg} --policy-name {waf}',
                 checks=[
                     self.check('managedRuleSets[0].ruleSetType', 'OWASP'),
                     self.check('managedRuleSets[0].ruleSetVersion', '3.1'),
                     self.check('managedRuleSets[0].ruleGroupOverrides[0].ruleGroupName', self.kwargs['csr_grp2'])
                 ])

        self.kwargs.update({
            'waf2': 'agp2',
            'csr_grp3': 'ExcessiveRequests'
        })

        # case 6: support Microsoft_HTTPDDoSRuleSet type, Medium is default sensitivity for this type if not specified
        self.cmd('network application-gateway waf-policy create -g {rg} -n {waf2} --version 3.2 --type owasp')
        self.cmd('network application-gateway waf-policy managed-rule rule-set add -g {rg} --policy-name {waf2} '
                 '--type Microsoft_HTTPDDoSRuleSet --version 1.0 --group-name {csr_grp3} '
                 '--rule rule-id=500100 '
                 '--rule rule-id=500110 sensitivity=low')
        self.cmd('network application-gateway waf-policy managed-rule rule-set list -g {rg} --policy-name {waf2}', checks=[
            self.check('managedRuleSets[1].ruleSetType', 'Microsoft_HTTPDDoSRuleSet'),
            self.check('managedRuleSets[1].ruleSetVersion', '1.0'),
            self.check('managedRuleSets[1].ruleGroupOverrides[0].ruleGroupName', self.kwargs['csr_grp3']),
            self.check('managedRuleSets[1].ruleGroupOverrides[0].rules[0].sensitivity', 'Medium'),
            self.check('managedRuleSets[1].ruleGroupOverrides[0].rules[1].sensitivity', 'Low')
        ])

    @ResourceGroupPreparer(name_prefix='cli_test_app_gateway_waf_policy_managed_rules_exclusion')
    def test_network_app_gateway_waf_policy_managed_rules_exclusions(self, resource_group):
        self.kwargs.update({
            'waf': 'agp1',
            'ip': 'pip1',
            'ag': 'ag1',
            'rg': resource_group
        })

        self.cmd('network application-gateway waf-policy create -g {rg} -n {waf}')

        # add one exclusion rule
        self.cmd('network application-gateway waf-policy managed-rule exclusion add -g {rg} --policy-name {waf} '
                 '--match-variable "RequestHeaderNames" --selector-match-operator "StartsWith" --selector "Bing"')
        self.cmd('network application-gateway waf-policy managed-rule exclusion list -g {rg} --policy-name {waf}',
                 checks=[
                     self.check('exclusions | length(@)', 1)
                 ])

        # add another exclusion rule
        self.cmd('network application-gateway waf-policy managed-rule exclusion add -g {rg} --policy-name {waf} '
                 '--match-variable "RequestHeaderNames" --selector-match-operator "Contains" --selector "Azure"')
        self.cmd('network application-gateway waf-policy managed-rule exclusion list -g {rg} --policy-name {waf}',
                 checks=[
                     self.check('exclusions | length(@)', 2)
                 ])

        # clear all exclusion rules
        self.cmd('network application-gateway waf-policy managed-rule exclusion remove  -g {rg} --policy-name {waf} ')
        self.cmd('network application-gateway waf-policy managed-rule exclusion list -g {rg} --policy-name {waf}',
                 checks=[
                     self.check('exclusions | length(@)', 0)
                 ])

    @ResourceGroupPreparer(name_prefix="cli_test_app_gateway_waf_policy_exclusion_rule_set_")
    def test_network_app_gateway_waf_policy_exclusion_rule_set(self, resource_group):
        self.kwargs.update({
            "waf": "agp",
            "rule_group1": "REQUEST-921-PROTOCOL-ATTACK",
            "rule_group2": "REQUEST-920-PROTOCOL-ENFORCEMENT",
        })
        # create a waf-policy
        self.cmd("network application-gateway waf-policy create -n {waf} -g {rg} --version 3.2 --type OWASP")
        # add one rule group to exclusion
        self.cmd(
            "network application-gateway waf-policy managed-rule exclusion rule-set add -g {rg} --policy-name {waf} \
            --match-variable RequestHeaderValues --match-operator Contains --selector Google \
            --type OWASP --version 3.2 \
            --group-name {rule_group1} --rule-ids 921140 921150",
            checks=[
                self.check("managedRules.exclusions[0].exclusionManagedRuleSets[0].ruleGroups[0].ruleGroupName", self.kwargs["rule_group1"]),
                self.check("managedRules.exclusions[0].exclusionManagedRuleSets[0].ruleGroups[0].rules | length(@)", 2),
                self.check("managedRules.exclusions[0].exclusionManagedRuleSets[0].ruleGroups[0].rules[0].ruleId", "921140"),
                self.check("managedRules.exclusions[0].exclusionManagedRuleSets[0].ruleGroups[0].rules[1].ruleId", "921150"),
            ]
        )
        # add another rule group to exclusion (with different matchers)
        self.cmd(
            "network application-gateway waf-policy managed-rule exclusion rule-set add -g {rg} --policy-name {waf} \
            --match-variable RequestHeaderNames --match-operator StartsWith --selector Bing \
            --type OWASP --version 3.2 \
            --group-name {rule_group2} --rule-ids 920340",
            checks=[
                self.check("managedRules.exclusions | length(@)", 2),
                self.check("managedRules.exclusions[1].exclusionManagedRuleSets[0].ruleGroups[0].ruleGroupName", self.kwargs["rule_group2"]),
                self.check("managedRules.exclusions[1].exclusionManagedRuleSets[0].ruleGroups[0].rules[0].ruleId", "920340"),
            ]
        )
        # add a rule group to the second exclusion
        self.cmd(
            "network application-gateway waf-policy managed-rule exclusion rule-set add -g {rg} --policy-name {waf} \
            --match-variable RequestHeaderNames --match-operator StartsWith --selector Bing \
            --type OWASP --version 3.2 \
            --group-name {rule_group1} --rule-ids 921140 921150",
            checks=[
                self.check("managedRules.exclusions[1].exclusionManagedRuleSets[0].ruleGroups[1].ruleGroupName", self.kwargs["rule_group1"]),
                self.check("managedRules.exclusions[1].exclusionManagedRuleSets[0].ruleGroups[1].rules | length(@)", 2),
                self.check("managedRules.exclusions[1].exclusionManagedRuleSets[0].ruleGroups[1].rules[0].ruleId", "921140"),
                self.check("managedRules.exclusions[1].exclusionManagedRuleSets[0].ruleGroups[1].rules[1].ruleId", "921150"),
            ]
        )
        # remove the first rule group
        self.cmd(
            "network application-gateway waf-policy managed-rule exclusion rule-set remove -g {rg} --policy-name {waf} \
            --match-variable RequestHeaderValues --match-operator Contains --selector Google \
            --type OWASP --version 3.2 --group-name {rule_group1}"
        )
        self.cmd(
            "network application-gateway waf-policy managed-rule exclusion rule-set list -g {rg} --policy-name {waf}",
            checks=[
                self.check("exclusions | length(@)", 1),
                self.check("exclusions[0].exclusionManagedRuleSets[0].ruleGroups[0].ruleGroupName", self.kwargs["rule_group2"]),
                self.check("exclusions[0].exclusionManagedRuleSets[0].ruleGroups[0].rules[0].ruleId", "920340"),
            ]
        )

    @ResourceGroupPreparer(name_prefix='cli_test_app_gateway_waf_policy_exception_', location='eastus2')
    def test_network_app_gateway_waf_policy_exception(self, resource_group):
        self.kwargs.update({
            'waf': 'agp1',
            'ip': 'pip1',
            'ag': 'ag1',
            'rg': resource_group
        })

        self.cmd('network application-gateway waf-policy create -g {rg} -n {waf}')

        self.cmd('network application-gateway waf-policy managed-rule exception add -g {rg} --policy-name {waf} '
                 '--match-variable "RequestURI" --value-match-operator "Contains" --values "health" "account/images" "default.aspx" '
                 '--rule-sets [0].rule-set-type=OWASP [0].rule-set-version=3.2')
        self.cmd('network application-gateway waf-policy managed-rule exception list -g {rg} --policy-name {waf}',
                 checks=[
                     self.check('exceptions | length(@)', 1)
                 ])
        self.cmd('network application-gateway waf-policy managed-rule exception remove -g {rg} --policy-name {waf}')
        self.cmd('network application-gateway waf-policy managed-rule exception list -g {rg} --policy-name {waf}',
                 checks=[
                     self.not_exists('exceptions')
                 ])

    @ResourceGroupPreparer(name_prefix='cli_test_app_gateway_waf_policy_compute_disabled_rule')
    def test_network_app_gateway_waf_policy_compute_disabled_rule(self, resource_group):
        self.kwargs.update({
            'policy_name': self.create_random_name('waf', 15),
            'policy_type': 'OWASP',
            'policy_version': 3.2,
            'rule_group_name': 'REQUEST-921-PROTOCOL-ATTACK',
            'rule_id': '921120'
        })

        self.cmd('network application-gateway waf-policy create -g {rg} '
                 '-n {policy_name} '
                 '--type {policy_type} '
                 '--version {policy_version}')

        self.cmd('network application-gateway waf-policy managed-rule rule-set add -g {rg} '
                 '--policy-name {policy_name} '
                 '--type {policy_type} '
                 '--version {policy_version} '
                 '--group-name {rule_group_name} '
                 '--rule rule-id={rule_id}',
                 checks=[
                     self.exists('managedRules.managedRuleSets[0].computedDisabledRules'),
                     self.check('managedRules.managedRuleSets[0].computedDisabledRules | length(@)', 1),
                     self.check('managedRules.managedRuleSets[0].computedDisabledRules[0].ruleGroupName', self.kwargs['rule_group_name']),
                     self.check('managedRules.managedRuleSets[0].computedDisabledRules[0].rules | length(@)', 1),
                     self.check('managedRules.managedRuleSets[0].computedDisabledRules[0].rules[0]', self.kwargs['rule_id']),
                 ])

        self.cmd('network application-gateway waf-policy managed-rule rule-set update -g {rg} '
                 '--policy-name {policy_name} '
                 '--type {policy_type} '
                 '--version {policy_version} '
                 '--group-name {rule_group_name} '
                 '--rule rule-id={rule_id} state=Enabled',
                 checks=[self.not_exists('managedRules.managedRuleSets[0].computedDisabledRules')])

        self.cmd('network application-gateway waf-policy managed-rule rule-set update -g {rg} '
                 '--policy-name {policy_name} '
                 '--type {policy_type} '
                 '--version {policy_version} '
                 '--group-name {rule_group_name} '
                 '--rule rule-id={rule_id} state=Disabled',
                 checks=[
                     self.exists('managedRules.managedRuleSets[0].computedDisabledRules'),
                     self.check('managedRules.managedRuleSets[0].computedDisabledRules | length(@)', 1),
                     self.check('managedRules.managedRuleSets[0].computedDisabledRules[0].ruleGroupName', self.kwargs['rule_group_name']),
                     self.check('managedRules.managedRuleSets[0].computedDisabledRules[0].rules | length(@)', 1),
                     self.check('managedRules.managedRuleSets[0].computedDisabledRules[0].rules[0]', self.kwargs['rule_id']),
                 ])

        self.cmd('network application-gateway waf-policy managed-rule rule-set list -g {rg} '
                 '--policy-name {policy_name}',
                 checks=[
                     self.exists('managedRuleSets[0].computedDisabledRules'),
                     self.check('managedRuleSets[0].computedDisabledRules | length(@)', 1),
                     self.check('managedRuleSets[0].computedDisabledRules[0].ruleGroupName', self.kwargs['rule_group_name']),
                     self.check('managedRuleSets[0].computedDisabledRules[0].rules | length(@)', 1),
                     self.check('managedRuleSets[0].computedDisabledRules[0].rules[0]', self.kwargs['rule_id']),
                 ])

        self.cmd('network application-gateway waf-policy managed-rule rule-set remove -g {rg} '
                 '--policy-name {policy_name} '
                 '--type {policy_type} '
                 '--version {policy_version} '
                 '--group-name {rule_group_name}',
                 checks=[self.not_exists('managedRules.managedRuleSets[0].computedDisabledRules')])


class NetworkDdosProtectionScenarioTest(LiveScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_ddos_protection', location='eastus2')
    def test_network_ddos_protection_plan(self, resource_group):

        self.kwargs.update({
            'vnet1': 'vnet1',
            'vnet2': 'vnet2',
            'ddos': 'ddos1'
        })

        self.cmd('network vnet create -g {rg} -n {vnet1}')
        self.kwargs['vnet2_id'] = self.cmd('network vnet create -g {rg} -n {vnet2}').get_output_in_json()['newVNet']['id']
        # can be attached through DDoS create
        self.kwargs['ddos_id'] = self.cmd('network ddos-protection create -g {rg} -n {ddos} --vnets {vnet1} {vnet2_id} --tags foo=doo').get_output_in_json()['id']
        self.cmd('network ddos-protection show -g {rg} -n {ddos}',
                 checks=[self.check('name', '{ddos}'),
                         self.check('provisioningState', 'Succeeded'),
                         self.check('length(virtualNetworks)', 2)])

        # can be detached through VNet update
        self.cmd('network vnet update -g {rg} -n {vnet1} --ddos-protection-plan ""')
        self.cmd('network vnet update -g {rg} -n {vnet2} --ddos-protection-plan ""')
        self.cmd('network ddos-protection show -g {rg} -n {ddos}')

        # can be attached through VNet update
        self.cmd('network vnet update -g {rg} -n {vnet1} --ddos-protection-plan {ddos}')
        self.cmd('network vnet update -g {rg} -n {vnet2} --ddos-protection-plan {ddos_id}')
        self.cmd('network ddos-protection show -g {rg} -n {ddos}')

        # can be detached through DDoS update
        self.cmd('network ddos-protection update -g {rg} -n {ddos} --tags doo=foo --vnets ""')
        self.cmd('network ddos-protection show -g {rg} -n {ddos}',
                 checks=[self.check('name', '{ddos}'),
                         self.check('provisioningState', 'Succeeded'),
                         self.check('virtualNetworks', None)])

        # can be attached through DDoS update
        self.cmd('network ddos-protection update -g {rg} -n {ddos} --vnets {vnet2_id} --tags foo=boo')
        self.cmd('network ddos-protection show -g {rg} -n {ddos}',
                 checks=[self.check('name', '{ddos}'),
                         self.check('provisioningState', 'Succeeded'),
                         self.check('length(virtualNetworks)', 1)])

        self.cmd('network ddos-protection list -g {rg}', checks=[self.check('length(@)', 1)])
        with self.assertRaises(Exception):
            self.cmd('network ddos-protection delete -g {rg} -n {ddos}')

        # remove all vnets and retry
        self.cmd('network ddos-protection update -g {rg} -n {ddos} --vnets ""')
        self.cmd('network ddos-protection delete -g {rg} -n {ddos}')


class NetworkPublicIpScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_public_ip', location="eastus2euap")
    def test_network_public_ip(self, resource_group):
        self.kwargs.update({
            'ip1': 'pubipdns',
            'ip2': 'pubipnodns',
            'ip3': 'pubip3',
            'dns': 'woot1',
            'zone': '1 2 3',
            'location': 'eastus2',
            'ip_tags': 'RoutingPreference=Internet',
            'version': 'ipv4',
            'sku': 'standard'
        })
        self.cmd('network public-ip create -g {rg} -n {ip1} --dns-name {dns} --dns-name-scope TenantReuse --allocation-method static', checks=[
            self.check('publicIp.provisioningState', 'Succeeded'),
            self.check('publicIp.publicIPAllocationMethod', 'Static'),
            self.check('publicIp.dnsSettings.domainNameLabel', '{dns}'),
            self.check('publicIp.dnsSettings.domainNameLabelScope', 'TenantReuse')
        ])
        self.cmd('network public-ip create -g {rg} -n {ip2}', checks=[
            self.check('publicIp.provisioningState', 'Succeeded'),
            self.check('publicIp.publicIPAllocationMethod', 'Static'),
            self.check('publicIp.dnsSettings', None)
        ])

        self.cmd('network public-ip create -g {rg} -n {ip3}'
                 ' --version {version} '
                 '--sku {sku} '
                 '--zone {zone} '
                 '-l {location} '
                 '--ip-tags {ip_tags} ',
                 checks=[
                     self.check('publicIp.provisioningState', 'Succeeded'),
                     self.check('publicIp.publicIPAllocationMethod', 'Static'),
                     self.check('publicIp.dnsSettings', None),
                     self.check('publicIp.ipTags[0].ipTagType', 'RoutingPreference'),
                     self.check('publicIp.ipTags[0].tag', 'Internet'),
        ])

        self.cmd(
            'network public-ip update -g {rg} -n {ip2} --allocation-method static --dns-name wowza2 --idle-timeout 10 --ip-tags null --tags foo=doo',
            checks=[
                self.check('publicIPAllocationMethod', 'Static'),
                self.check('dnsSettings.domainNameLabel', 'wowza2'),
                self.check('idleTimeoutInMinutes', 10),
                self.check('tags.foo', 'doo'),
                self.check("ipTags", [])
            ])

        self.cmd('network public-ip list -g {rg}', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?resourceGroup == '{rg}']) == length(@)", True)
        ])

        self.cmd('network public-ip show -g {rg} -n {ip1}', checks=[
            self.check('type(@)', 'object'),
            self.check('name', '{ip1}'),
            self.check('resourceGroup', '{rg}')
        ])

        self.cmd('network public-ip delete -g {rg} -n {ip1}')
        self.cmd('network public-ip list -g {rg}',
                 checks=self.check("length[?name == '{ip1}']", None))

    @ResourceGroupPreparer(name_prefix='cli_test_public_ip_zone', location='eastus2')
    def test_network_public_ip_zone(self, resource_group):
        self.cmd('network public-ip create -g {rg} -n ip --sku Standard -z 1 2 3', checks=[
            self.check('length(publicIp.zones)', 3)
        ])

    @ResourceGroupPreparer(name_prefix='cli_test_public_ip_ddos_settings', location='eastus2')
    def test_network_public_ip_ddos_settings(self, resource_group):

        self.kwargs.update({
            'ip1': 'pubipddos',
            'ddos': 'ddos1',
        })

        self.kwargs['ddos_id'] = self.cmd('network ddos-protection create -g {rg} -n {ddos}').get_output_in_json()['id']

        self.cmd(
            'network public-ip create -g {rg} -n {ip1} --protection-mode Enabled --sku Standard --ddos-protection-plan {ddos}',
            checks=[
                self.check('publicIp.ddosSettings.protectionMode', 'Enabled'),
                self.check('publicIp.ddosSettings.ddosProtectionPlan.id', '{ddos_id}'),
                self.check('publicIp.name', '{ip1}'),
                self.check('publicIp.provisioningState', 'Succeeded')
            ])

        # test ddos protection status
        self.cmd('network application-gateway create -g {rg} -n testag --public-ip-address {ip1} --sku Standard_v2 --priority 1001')
        self.cmd('network public-ip ddos-protection show -g {rg} -n {ip1}', self.check('isWorkloadProtected', True))
        self.cmd('network public-ip update -g {rg} -n {ip1} --protection-mode Disabled --ddos-protection-plan null',
                 checks=[
                     self.check('ddosSettings.protectionMode', 'Disabled'),
                     self.check('ddosSettings.ddosProtectionPlan', None),
                     self.check('name', '{ip1}'),
                     self.check('provisioningState', 'Succeeded')
                 ])
        self.cmd('network ddos-protection delete -g {rg} -n {ddos}')

        self.cmd('network application-gateway delete -g {rg} -n testag')
        self.cmd('network public-ip delete -g {rg} -n {ip1}')
        self.cmd('network public-ip list -g {rg}',
                 checks=self.check("length[?name == '{ip1}']", None))


class NetworkZonedPublicIpScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_zoned_public_ip')
    def test_network_zoned_public_ip(self, resource_group):
        self.kwargs['ip'] = 'pubip'
        self.cmd('network public-ip create -g {rg} -n {ip} -l centralus -z 2 --sku standard',
                 checks=self.check('publicIp.zones[0]', '2'))

        self.cmd(
            'network public-ip show -g {rg} -n {ip}',
            checks=[
                self.check('name', '{ip}'),
                self.check('publicIPAddressVersion', 'IPv4')
            ]
        )


class NetworkRouteFilterScenarioTest(ScenarioTest):

    @AllowLargeResponse()
    @ResourceGroupPreparer(name_prefix='cli_test_network_route_filter')
    def test_network_route_filter(self, resource_group):
        self.kwargs['filter'] = 'filter1'
        self.kwargs['rg'] = resource_group
        self.cmd('network route-filter create -g {rg} -n {filter} --tags foo=doo')
        self.cmd('network route-filter update -g {rg} -n {filter}')
        self.cmd('network route-filter show -g {rg} -n {filter}')
        self.cmd('network route-filter list -g {rg}')


        self.cmd('network route-filter rule list-service-communities')
        self.cmd('network route-filter rule create -g {rg} --filter-name {filter} -n rule1 --communities 12076:5040 12076:5030 --access allow')
        self.cmd('network route-filter rule update -g {rg} --filter-name {filter} -n rule1')
        self.cmd('network route-filter rule show -g {rg} --filter-name {filter} -n rule1')
        self.cmd('network route-filter rule list -g {rg} --filter-name {filter}')
        self.cmd('network route-filter rule delete -g {rg} --filter-name {filter} -n rule1')

        self.cmd('network route-filter delete -g {rg} -n {filter}')


class NetworkExpressRouteScenarioTest(ScenarioTest):

    def _test_express_route_peering(self):

        def _create_peering(peering, peer_asn, vlan, primary_prefix, secondary_prefix):
            self.kwargs.update({
                'peering': peering,
                'asn': peer_asn,
                'vlan': vlan,
                'pri_prefix': primary_prefix,
                'sec_prefix': secondary_prefix
            })
            self.cmd('network express-route peering create -g {rg} --circuit-name {er} --peering-type {peering} --peer-asn {asn} --vlan-id {vlan} --primary-peer-subnet {pri_prefix} --secondary-peer-subnet {sec_prefix}')

        # create private peerings
        _create_peering('AzurePrivatePeering', 10001, 101, '102.0.0.0/30', '103.0.0.0/30')

        self.cmd('network express-route peering create -g {rg} --circuit-name {er} --peering-type MicrosoftPeering --peer-asn 10002 --vlan-id 103 --primary-peer-subnet 104.0.0.0/30 --secondary-peer-subnet 105.0.0.0/30 --advertised-public-prefixes 104.0.0.0/30 --customer-asn 10000 --routing-registry-name level3')
        self.cmd('network express-route peering show -g {rg} --circuit-name {er} -n MicrosoftPeering', checks=[
            self.check('microsoftPeeringConfig.advertisedPublicPrefixes[0]', '104.0.0.0/30'),
            self.check('microsoftPeeringConfig.customerASN', 10000),
            self.check('microsoftPeeringConfig.routingRegistryName', 'LEVEL3')
        ])

        self.cmd('network express-route peering delete -g {rg} --circuit-name {er} -n MicrosoftPeering')

        self.cmd('network express-route peering list --resource-group {rg} --circuit-name {er}',
                 checks=self.check('length(@)', 1))

        self.cmd('network express-route peering update -g {rg} --circuit-name {er} -n AzurePrivatePeering --set vlanId=200',
                 checks=self.check('vlanId', 200))

    def _test_express_route_auth(self):

        self.cmd('network express-route auth create -g {rg} --circuit-name {er} -n auth1',
                 checks=self.check('authorizationUseStatus', 'Available'))

        self.cmd('network express-route auth list --resource-group {rg} --circuit-name {er}',
                 checks=self.check('length(@)', 1))

        self.cmd('network express-route auth show -g {rg} --circuit-name {er} -n auth1',
                 checks=self.check('authorizationUseStatus', 'Available'))

        self.cmd('network express-route auth delete -g {rg} --circuit-name {er} -n auth1')

        self.cmd('network express-route auth list --resource-group {rg} --circuit-name {er}', checks=self.is_empty())

    @record_only()  # record_only as the express route is extremely expensive, contact service team for an available ER
    @ResourceGroupPreparer(name_prefix='cli_test_express_route')
    def test_network_express_route(self, resource_group):

        self.kwargs = {
            'rg': resource_group,
            'er': 'circuit1',
            'rt': 'Microsoft.Network/expressRouteCircuits'
        }

        self.cmd('network express-route list-service-providers', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?type == 'Microsoft.Network/expressRouteServiceProviders']) == length(@)", True)
        ])

        # Premium SKU required to create MicrosoftPeering settings
        self.cmd('network express-route create -g {rg} -n {er} --bandwidth 50 --provider "Ibiza Test Provider" --peering-location Area51 --sku-tier Premium --tags foo=doo')
        self.cmd('network express-route list', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?type == '{rt}']) == length(@)", True)
        ])
        self.cmd('network express-route list --resource-group {rg}', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?type == '{rt}']) == length(@)", True),
            self.check("length([?resourceGroup == '{rg}']) == length(@)", True)
        ])
        self.cmd('network express-route show --resource-group {rg} --name {er}', checks=[
            self.check('type(@)', 'object'),
            self.check('type', '{rt}'),
            self.check('name', '{er}'),
            self.check('resourceGroup', '{rg}'),
            self.check('tags.foo', 'doo')
        ])
        self.cmd('network express-route get-stats --resource-group {rg} --name {er}',
                 checks=self.check('type(@)', 'object'))

        self.cmd('network express-route update -g {rg} -n {er} --set tags.test=Test', checks=[
            self.check('tags.test', 'Test')
        ])

        self.cmd('network express-route update -g {rg} -n {er} --tags foo=boo',
                 checks=self.check('tags.foo', 'boo'))

        self._test_express_route_auth()

        self._test_express_route_peering()

        # because the circuit isn't actually provisioned, these commands will not return anything useful
        # so we will just verify that the command makes it through the SDK without error.
        self.cmd('network express-route list-arp-tables --resource-group {rg} --name {er} --peering-name azureprivatepeering --path primary')
        self.cmd('network express-route list-route-tables --resource-group {rg} --name {er} --peering-name azureprivatepeering --path primary')
        self.cmd('network express-route list-route-tables-summary --resource-group {rg} --name {er} --peering-name azureprivatepeering --path primary')

        self.cmd('network express-route delete --resource-group {rg} --name {er}')
        # Expecting no results as we just deleted the only express route in the resource group
        self.cmd('network express-route list --resource-group {rg}', checks=self.is_empty())

        with self.assertRaisesRegex(CLIError, 'Please provide a complete resource ID'):
            self.cmd('network express-route gateway connection show --ids /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myrg/providers/Microsoft.Network/expressRouteGateways/aaa')

    @unittest.skip('Test is wrong, please fix. rg not found')
    @ResourceGroupPreparer(name_prefix='cli_test_express_route')
    def test_network_express_route_connection_routing_configuration(self, resource_group):
        self.kwargs = {
            'rg': 'dedharrtv3final',
            'gw': '16297a6ff5314c0f8d0eb580aa7861b3-eastus-er-gw',
            'connection': 'yuerconnection',
            'peering': '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/dedharrtv3final/providers/Microsoft.Network/expressRouteCircuits/clicktfinal/peerings/AzurePrivatePeering',
            'route_table1': '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/dedharrtv3final/providers/Microsoft.Network/virtualHubs/blhub/hubRouteTables/routetable1',
            'route_table2': '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/dedharrtv3final/providers/Microsoft.Network/virtualHubs/blhub/hubRouteTables/routetable2'
        }

        self.cmd('network express-route gateway connection update '
                 '-n {connection} '
                 '-g {rg} '
                 '--gateway-name {gw} '
                 '--peering {peering} '
                 '--associated-route-table {route_table1} '
                 '--propagated-route-tables {route_table1} {route_table2} '
                 '--labels label1 label2',
                 checks=[
                     self.check('provisioningState', 'Succeeded'),
                     self.check('name', self.kwargs['connection']),
                     self.check('routingConfiguration.associatedRouteTable.id', self.kwargs['route_table1']),
                     self.check('length(routingConfiguration.propagatedRouteTables.ids)', 2),
                     self.check('routingConfiguration.propagatedRouteTables.ids[0].id', self.kwargs['route_table1']),
                     self.check('routingConfiguration.propagatedRouteTables.ids[1].id', self.kwargs['route_table2']),
                     self.check('length(routingConfiguration.propagatedRouteTables.labels)', 2),
                     self.check('routingConfiguration.propagatedRouteTables.labels[0]', 'label1'),
                     self.check('routingConfiguration.propagatedRouteTables.labels[1]', 'label2')])

        self.cmd('network express-route gateway connection show -n {connection} -g {rg} --gateway-name {gw}', checks=[
            self.check('provisioningState', 'Succeeded'),
            self.check('name', self.kwargs['connection']),
            self.check('routingConfiguration.associatedRouteTable.id', self.kwargs['route_table1']),
            self.check('length(routingConfiguration.propagatedRouteTables.ids)', 2),
            self.check('routingConfiguration.propagatedRouteTables.ids[0].id', self.kwargs['route_table1']),
            self.check('routingConfiguration.propagatedRouteTables.ids[1].id', self.kwargs['route_table2']),
            self.check('length(routingConfiguration.propagatedRouteTables.labels)', 2),
            self.check('routingConfiguration.propagatedRouteTables.labels[0]', 'label1'),
            self.check('routingConfiguration.propagatedRouteTables.labels[1]', 'label2')
        ])

    @unittest.skip('The required extension command has not been release')
    @ResourceGroupPreparer(name_prefix='cli_test_express_route_gateway_connection_inbound_outbound_routemap')
    def test_express_route_gateway_connection_inbound_outbound_routemap(self, resource_group):
        self.kwargs.update({
            'vwan': self.create_random_name('vwan', 10),
            'vhub': self.create_random_name('vhub', 10),
            'er': self.create_random_name("er", 10),
            'ergateway': self.create_random_name("ergw", 16),
            'ergatewayconn': self.create_random_name("ergw", 16),
            "route_map_name": self.create_random_name("routemap-", 16),
            "route_map_name_2": self.create_random_name("routemap-", 16),
            "route_map_name_3": self.create_random_name("routemap-", 16),
            "route_map_name_4": self.create_random_name("routemap-", 16)
        })

        self.cmd('network vwan create -n {vwan} -g {rg} --type Standard')
        self.cmd('network vhub create -g {rg} -n {vhub} --vwan {vwan}  --address-prefix 10.5.0.0/16 --sku Standard')
        route_map_id = self.cmd("network vhub route-map create -n {route_map_name} -g {rg} --vhub-name {vhub}").get_output_in_json()['id']
        route_map_id_2 = self.cmd("network vhub route-map create -n {route_map_name_2} -g {rg} --vhub-name {vhub}").get_output_in_json()['id']
        route_map_id_3 = self.cmd("network vhub route-map create -n {route_map_name_3} -g {rg} --vhub-name {vhub}").get_output_in_json()['id']
        route_map_id_4 = self.cmd("network vhub route-map create -n {route_map_name_4} -g {rg} --vhub-name {vhub}").get_output_in_json()['id']
        self.kwargs.update({
            'route_map_id': route_map_id,
            'route_map_id_2': route_map_id_2,
            'route_map_id_3': route_map_id_3,
            'route_map_id_4': route_map_id_4
        })
        self.cmd('network express-route create -g {rg} -n {er} --bandwidth 50 --provider "Ibiza Test Provider" --peering-location Area51 --sku-tier Premium')
        self.cmd('network express-route gateway create -g {rg} -n {ergateway} --virtual-hub {vhub}')
        # self.cmd('network express-route peering create -g {rg} --circuit-name {er} --peering-type AzurePrivatePeering --peer-asn 10001 --vlan-id 101 --primary-peer-subnet 102.0.0.0/30 --secondary-peer-subnet 103.0.0.0/30')
        peer_id = self.cmd('network express-route peering create -g {rg} --circuit-name {er} --peering-type MicrosoftPeering --peer-asn 10002 --vlan-id 103 --primary-peer-subnet 104.0.0.0/30 --secondary-peer-subnet 105.0.0.0/30 --advertised-public-prefixes 104.0.0.0/30 --customer-asn 10000 --routing-registry-name level3').get_output_in_json()['id']
        self.kwargs.update({
            'peer_id': peer_id
        })

        with self.assertRaises(Exception):
            self.cmd('network express-route gateway connection create -g {rg} -n {ergatewayconn} --gateway-name {ergateway} --peering {peer_id} --inbound-route-map {{id:{route_map_id}}} --outbound-route-map {{id:{route_map_id_2}}}')
        self.cmd('network express-route gateway connection show -n {ergatewayconn} -g {rg} --gateway-name {ergateway}', checks=[
            self.check('routingConfiguration.inboundRouteMap.id', '{route_map_id}'),
            self.check('routingConfiguration.outboundRouteMap.id', '{route_map_id_2}')
        ])
        with self.assertRaises(Exception):
            self.cmd('network express-route gateway connection update -g {rg} -n {ergatewayconn} --gateway-name {ergateway} --inbound-route-map {{id:{route_map_id_3}}} --outbound-route-map {{id:{route_map_id_4}}}')
        self.cmd('network express-route gateway connection show -n {ergatewayconn} -g {rg} --gateway-name {ergateway}', checks=[
            self.check('routingConfiguration.inboundRouteMap.id', '{route_map_id_3}'),
            self.check('routingConfiguration.outboundRouteMap.id', '{route_map_id_4}')
        ])


class NetworkExpressRoutePortScenarioTest(ScenarioTest):

    def __init__(self, method_name):
        super().__init__(method_name, recording_processors=[
            ExpressRoutePortLOAContentReplacer()
        ])

    @AllowLargeResponse()
    @ResourceGroupPreparer(name_prefix='cli_test_express_route_port', location='eastus')
    @KeyVaultPreparer(name_prefix='test-er-port-kv', location='eastus', additional_params='--enable-rbac-authorization false')
    def test_network_express_route_port(self, resource_group, key_vault):
        self.kwargs.update({
            'rg': resource_group,
            'location': 'eastus',
            'name': 'expressRouteTest',
            'peeringRG': 'Equinix-Ashburn-DC2',
            'encapsulation': 'QinQ',
            'bandwidth': '10 Gbps',
            'cipher': 'GcmAes128',
            'kv': key_vault,
            'CAK_name': 'CAK',
            'CAK_value': 'b4355b9ccaf727d2ba7744ee991ce00e',
            'CKN_name': 'CKN',
            'CKN_value': '93e9ce8469eff0536784fc4ad253b5a6',
        })
        self.kwargs['CAK_id'] = self.cmd('keyvault secret set --name {CAK_name} --vault-name {kv} --value {CAK_value}').get_output_in_json()['id']
        self.kwargs['CKN_id'] = self.cmd('keyvault secret set --name {CKN_name} --vault-name {kv} --value {CKN_value}').get_output_in_json()['id']
        identity = self.cmd('identity create -g {rg} -n {name}').get_output_in_json()
        self.cmd('keyvault set-policy -n {kv} -g {rg} --secret-permissions get --object-id ' + identity['principalId'])

        self.cmd('network express-route port location list')

        self.cmd('network express-route port location show -l {peeringRG}', checks=[
            self.check('name', self.kwargs['peeringRG'])
        ])

        self.cmd('network express-route port create -g {rg} -n {name} --location {location} --peering-location {peeringRG} --encapsulation {encapsulation} --bandwidth {bandwidth}', checks=[
            self.check('name', self.kwargs['name']),
            self.check('length(links)', 2),
        ])
        self.cmd('network express-route port list -g {rg}', checks=[
            self.check('length(@)', 1)
        ])
        self.cmd('network express-route port show -g {rg} -n {name}')

        self.cmd('network express-route port identity assign -g {rg} -n {name} --identity ' + identity['id'])

        self.cmd('network express-route port identity show -g {rg} -n {name}')

        self.cmd('network express-route port link list -g {rg} --port-name {name}', checks=[
            self.check('length(@)', 2)
        ])
        self.cmd('network express-route port link show -g {rg} --port-name {name} -n link1', checks=[
            self.check('name', 'link1')
        ])

        self.cmd('network express-route port link update -g {rg} --port-name {name} -n link1 '
                 '--macsec-ckn-secret-identifier {CKN_id} --macsec-cak-secret-identifier {CAK_id} '
                 '--macsec-cipher {cipher} --admin-state', checks=[
            self.check('adminState', 'Enabled'),
            self.check('macSecConfig.cakSecretIdentifier', self.kwargs['CAK_id']),
            self.check('macSecConfig.cknSecretIdentifier', self.kwargs['CKN_id']),
            self.check('macSecConfig.cipher', self.kwargs['cipher']),
        ])

        self.cmd('network express-route port generate-loa --customer-name MyCustomer -g {rg} --name {name} -f loa1')

class NetworkExpressRouteCircuitLinkFailoverBasicScenarioTest(ScenarioTest):
    @live_only()
    def test_start_circuit_link_failover_test(self): # live_only as the express route is extremely expensive, contact service team for an available ER
        resource_group = "CircuitFailoverTestsBothLinks04"  
        circuit_name = "ErCircuit01"
        peering_location = "Noida2"

        self.kwargs.update({
            'rg': resource_group,
            'circuit': circuit_name,
            'peering_loc': peering_location,
            'link_type': 'Secondary',
            'maintenance_category': 'BgpDisconnect',
            'fetch_latest': True,
            'test_type': 'LinkFailover',
        })

        # Run the command
        result = self.cmd(
            'network express-route start-link-failover-test '
            '-g {rg} --name {circuit} '
            '--link-type {link_type} '
            '--maintenance-category {maintenance_category}'
        ).get_output_in_json()

        # Validate that result is a string (per _schema_on_200 = AAZStrType())
        self.assertIsInstance(result, dict)

    @live_only()
    def test_stop_circuit_link_failover_test(self): # live_only as the express route is extremely expensive, contact service team for an available ER
        import time

        time.sleep(2 * 60)  # 120 seconds To wait for sometime before stopping the test failover
        resource_group = "CircuitFailoverTestsBothLinks04"  
        circuit_name = "ErCircuit01"
        peering_location = "Noida2"
        simulation_successful = True
        test_guid = "c84fe369-b52c-4b66-87c7-ec873235c9c1"

        self.kwargs.update({
            'rg': resource_group,
            'circuit': circuit_name,
            'peering_loc': peering_location,
            'link_type': 'Secondary',
            'maintenance_category': 'BgpDisconnect',
            'fetch_latest': True,
            'test_type': 'LinkFailover',
            'simulation_successful': simulation_successful,
            'is_verified': True,
            'test_guid': test_guid,
        })

        # Run the command
        result = self.cmd(
            'network express-route stop-link-failover-test '
            '-g {rg} --name {circuit} '
            '--circuit-test-category {maintenance_category} '
            '--link-type {link_type} '
            '--simulation-successful {simulation_successful} '
            '--is-verified {is_verified}'
        ).get_output_in_json()

        # Validate
        self.assertTrue(isinstance(result, (str, dict)))

        # Run all tests detail command to validate the stop operation
        tests_link_latest = self.cmd(
            'network express-route get-link-failover-all-tests-detail '
            '-g {rg} --name {circuit} '
            '--fetch-latest True --type LinkFailover'
        ).get_output_in_json()

        self.assertIsInstance(tests_link_latest, dict)

        #
        single_test_result = self.cmd(
                'network express-route get-link-failover-single-test-detail '
                '-g {rg} --name {circuit} '
                '--failover-test-id {test_guid} '
                '--link-type {link_type} '
                '--maintenance-category {maintenance_category}'
            ).get_output_in_json()

        # Validate response structure
        self.assertIsInstance(single_test_result, dict)


class NetworkExpressRouteIPv6PeeringScenarioTest(ScenarioTest):

    @record_only()  # record_only as the express route is extremely expensive, contact service team for an available ER
    @ResourceGroupPreparer(name_prefix='cli_test_express_route_ipv6_peering')
    def test_network_express_route_ipv6_peering(self, resource_group):

        self.kwargs['er'] = 'circuit1'

        # Premium SKU required to create MicrosoftPeering settings
        self.cmd('network express-route create -g {rg} -n {er} --bandwidth 50 --provider "Ibiza Test Provider" --peering-location Area51 --sku-tier Premium')
        self.cmd('network express-route peering create -g {rg} --circuit-name {er} --peering-type MicrosoftPeering --peer-asn 10002 --vlan-id 103 --primary-peer-subnet 104.0.0.0/30 --secondary-peer-subnet 105.0.0.0/30 --advertised-public-prefixes 104.0.0.0/30 --customer-asn 10000 --routing-registry-name level3')
        self.cmd('network express-route peering update -g {rg} --circuit-name {er} -n MicrosoftPeering --ip-version ipv6 --primary-peer-subnet 2001:db00::/126 --secondary-peer-subnet 2002:db00::/126 --advertised-public-prefixes 2001:db00::/126 --customer-asn 100001 --routing-registry-name level3')
        self.cmd('network express-route peering show -g {rg} --circuit-name {er} -n MicrosoftPeering', checks=[
            self.check('microsoftPeeringConfig.advertisedPublicPrefixes[0]', '104.0.0.0/30'),
            self.check('microsoftPeeringConfig.customerASN', 10000),
            self.check('microsoftPeeringConfig.routingRegistryName', 'LEVEL3'),
            self.check('ipv6PeeringConfig.microsoftPeeringConfig.advertisedPublicPrefixes[0]', '2001:db00::/126'),
            self.check('ipv6PeeringConfig.microsoftPeeringConfig.customerASN', 100001),
            self.check('ipv6PeeringConfig.state', 'Enabled')
        ])
        self.cmd('network express-route peering get-stats -g {rg} --circuit-name {er} -n MicrosoftPeering', checks=[
            self.check('type(@)', 'object'),
        ])

    @record_only()  # record_only as the express route is extremely expensive, contact service team for an available ER
    @ResourceGroupPreparer(name_prefix='cli_test_express_route_ipv6_peering2', location='eastus')
    def test_network_express_route_ipv6_peering2(self, resource_group):
        self.kwargs['er'] = 'test_circuit'
        # create with ipv6
        self.cmd('network express-route create -g {rg} -n {er} --bandwidth 50 --provider "Ibiza Test Provider" '
                 '--peering-location Area51 --sku-tier Premium')
        self.cmd('network express-route peering create -g {rg} --circuit-name {er} --peering-type AzurePrivatePeering '
                 '--peer-asn 10002 --vlan-id 103 --ip-version ipv6 --primary-peer-subnet 2002:db00::/126 '
                 '--secondary-peer-subnet 2003:db00::/126',
                 checks=[self.check('ipv6PeeringConfig.primaryPeerAddressPrefix', '2002:db00::/126'),
                         self.check('ipv6PeeringConfig.secondaryPeerAddressPrefix', '2003:db00::/126')])


class NetworkExpressRouteGlobalReachScenarioTest(ScenarioTest):

    @record_only()  # record_only as the express route is extremely expensive, contact service team for an available ER
    @ResourceGroupPreparer(name_prefix='cli_test_express_route_global_reach')
    def test_network_express_route_global_reach(self, resource_group):
        from azure.core.exceptions import HttpResponseError
        self.kwargs.update({
            'er1': 'er1',
            'er2': 'er2',
            'conn12': 'conn12',
        })

        self.cmd('network express-route create -g {rg} -n {er1} --allow-global-reach --bandwidth 50 --peering-location Area51 --provider "Microsoft ER Test" --sku-tier Premium')
        self.cmd('network express-route peering create -g {rg} --circuit-name {er1} --peering-type AzurePrivatePeering --peer-asn 10001 --vlan-id 101 --primary-peer-subnet 102.0.0.0/30 --secondary-peer-subnet 103.0.0.0/30')

        self.cmd('network express-route create -g {rg} -n {er2} --allow-global-reach --bandwidth 50 --peering-location "Denver Test" --provider "Test Provider NW" --sku-tier Premium')
        self.cmd('network express-route peering create -g {rg} --circuit-name {er2} --peering-type AzurePrivatePeering --peer-asn 10002 --vlan-id 102 --primary-peer-subnet 104.0.0.0/30 --secondary-peer-subnet 105.0.0.0/30')

        # These commands won't succeed because circuit creation requires a manual step from the service.
        with self.assertRaisesRegex(HttpResponseError, 'is Not Provisioned'):
            self.cmd('network express-route peering connection create -g {rg} --circuit-name {er1} --peering-name AzurePrivatePeering -n {conn12} --peer-circuit {er2} --address-prefix 104.0.0.0/29')
        self.cmd('network express-route peering connection show -g {rg} --circuit-name {er1} --peering-name AzurePrivatePeering -n {conn12}')
        self.cmd('network express-route peering connection list -g {rg} --circuit-name {er1} --peering-name AzurePrivatePeering')
        self.cmd('network express-route peering connection delete -g {rg} --circuit-name {er1} --peering-name AzurePrivatePeering -n {conn12}')

    @record_only()  # record_only as the express route is extremely expensive, contact service team for an available ER
    @ResourceGroupPreparer(name_prefix='cli_test_express_route_peer_connection')
    def test_network_express_route_peer_connection(self, resource_group):
        from azure.core.exceptions import ResourceNotFoundError
        self.kwargs.update({
            'er1': 'er1',
            'er2': 'er2',
            'peconn12': 'peconn12',
        })

        self.cmd('network express-route create -g {rg} -n {er1} --allow-global-reach --bandwidth 50 --peering-location Area51 --provider "Microsoft ER Test" --sku-tier Premium')
        self.cmd('network express-route peering create -g {rg} --circuit-name {er1} --peering-type AzurePrivatePeering --peer-asn 10001 --vlan-id 101 --primary-peer-subnet 102.0.0.0/30 --secondary-peer-subnet 103.0.0.0/30')

        self.cmd('network express-route create -g {rg} -n {er2} --allow-global-reach --bandwidth 50 --peering-location "Denver Test" --provider "Test Provider NW" --sku-tier Premium')
        self.cmd('network express-route peering create -g {rg} --circuit-name {er2} --peering-type AzurePrivatePeering --peer-asn 10002 --vlan-id 102 --primary-peer-subnet 104.0.0.0/30 --secondary-peer-subnet 105.0.0.0/30')

        # cannot create it, so this test will fail due to resource is not found.
        with self.assertRaisesRegex(ResourceNotFoundError, 'NotFound'):
            self.cmd('network express-route peering peer-connection show -g {rg} --circuit-name {er1} --peering-name AzurePrivatePeering -n {peconn12}')
        self.cmd('network express-route peering peer-connection list -g {rg} --circuit-name {er1} --peering-name AzurePrivatePeering')

    @record_only()  # record_only as the express route is extremely expensive, contact service team for an available ER
    @ResourceGroupPreparer(name_prefix='cli_test_express_route_global_reach_config')
    def test_network_express_route_global_reach_config(self, resource_group):
        from azure.core.exceptions import HttpResponseError
        self.kwargs.update({
            'er1': 'er1',
            'er2': 'er2',
            'conn12': 'conn12',
        })

        self.cmd('network express-route create -g {rg} -n {er1} --allow-global-reach --bandwidth 50 --peering-location Area51 --provider "Microsoft ER Test" --sku-tier Premium')
        self.cmd('network express-route peering create -g {rg} --circuit-name {er1} --peering-type AzurePrivatePeering --peer-asn 10001 --vlan-id 101 --primary-peer-subnet 102.0.0.0/30 --secondary-peer-subnet 103.0.0.0/30')

        self.cmd('network express-route create -g {rg} -n {er2} --allow-global-reach --bandwidth 50 --peering-location "Denver Test" --provider "Test Provider NW" --sku-tier Premium')
        self.cmd('network express-route peering create -g {rg} --circuit-name {er2} --peering-type AzurePrivatePeering --peer-asn 10002 --vlan-id 102 --primary-peer-subnet 104.0.0.0/30 --secondary-peer-subnet 105.0.0.0/30')

        # These commands won't succeed because circuit creation requires a manual step from the service.
        with self.assertRaisesRegex(HttpResponseError, 'is Not Provisioned'):
            self.cmd('network express-route peering connection create -g {rg} --circuit-name {er1} --peering-name AzurePrivatePeering -n {conn12} --peer-circuit {er2} --address-prefix 104.0.0.0/29')
        with self.assertRaisesRegex(HttpResponseError, 'ParentResourceIsInFailedState'):
            self.cmd('network express-route peering connection ipv6-config set -g {rg} --circuit-name {er1} --peering-name AzurePrivatePeering -n {conn12} --address-prefix .../125')
        with self.assertRaisesRegex(HttpResponseError, 'ParentResourceIsInFailedState'):
            self.cmd('network express-route peering connection ipv6-config remove -g {rg} --circuit-name {er1} --peering-name AzurePrivatePeering -n {conn12}')
        self.cmd('network express-route peering connection delete -g {rg} --circuit-name {er1} --peering-name AzurePrivatePeering -n {conn12}')


class NetworkCrossRegionLoadBalancerScenarioTest(ScenarioTest):

    @AllowLargeResponse()
    @ResourceGroupPreparer(name_prefix='cli_test_cr_load_balancer')
    def test_network_cross_region_lb(self, resource_group):

        self.kwargs.update({
            'lb': 'cross-region-lb',
            'rg': resource_group,
            'rt': 'Microsoft.Network/loadBalancers',
            'pub_ip': 'publicip4'
        })

        # test lb create with min params (new ip)
        self.cmd('network cross-region-lb create -n {lb}1 -g {rg}', checks=[
            self.check('loadBalancer.frontendIPConfigurations[0].properties.privateIPAllocationMethod', 'Dynamic'),
            self.check('loadBalancer.frontendIPConfigurations[0].resourceGroup', '{rg}')
        ])

        # test internet facing load balancer with new static public IP
        self.cmd('network cross-region-lb create -n {lb}2 -g {rg} --public-ip-address-allocation static --tags foo=doo')
        self.cmd('network public-ip show -g {rg} -n PublicIP{lb}2', checks=[
            self.check('publicIPAllocationMethod', 'Static'),
            self.check('tags.foo', 'doo')
        ])

        # test internet facing load balancer with existing public IP (by name)
        self.cmd('network public-ip create -n {pub_ip} -g {rg} --sku Standard --tier Global')
        self.cmd('network cross-region-lb create -n {lb}3 -g {rg} --public-ip-address {pub_ip}', checks=[
            self.check('loadBalancer.frontendIPConfigurations[0].properties.privateIPAllocationMethod', 'Dynamic'),
            self.check('loadBalancer.frontendIPConfigurations[0].resourceGroup', '{rg}'),
            self.check("loadBalancer.frontendIPConfigurations[0].properties.publicIPAddress.contains(id, '{pub_ip}')", True)
        ])

        self.cmd('network cross-region-lb list', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?type == '{rt}']) == length(@)", True)
        ])
        self.cmd('network cross-region-lb list --resource-group {rg}', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?type == '{rt}']) == length(@)", True),
            self.check("length([?resourceGroup == '{rg}']) == length(@)", True)
        ])
        self.cmd('network cross-region-lb show --resource-group {rg} --name {lb}1', checks=[
            self.check('type(@)', 'object'),
            self.check('type', '{rt}'),
            self.check('resourceGroup', '{rg}'),
            self.check('name', '{lb}1')
        ])
        # test cross-region-lb update
        self.cmd(
            'network cross-region-lb update --resource-group {rg} --name {lb}1 --set tags.CostCenter=MyBusinessGroup',
            checks=[
                self.check('tags.CostCenter', 'MyBusinessGroup')
            ])
        self.cmd('network cross-region-lb delete --resource-group {rg} --name {lb}1')
        # Expecting no results as we just deleted the only lb in the resource group
        self.cmd('network cross-region-lb list --resource-group {rg}', checks=self.check('length(@)', 2))

    @ResourceGroupPreparer(name_prefix='cli_test_cross_region_load_balancer_ip_config')
    def test_network_cross_region_load_balancer_ip_config(self, resource_group):

        for i in range(1, 4):  # create 3 public IPs to use for the test
            self.cmd('network public-ip create -g {{rg}} -n publicip{} --sku Standard --tier Global'.format(i))

        # create internet-facing LB with public IP (lb1)
        self.cmd('network cross-region-lb create -g {rg} -n lb1 --public-ip-address publicip1')

        # Test frontend IP configuration for internet-facing LB
        self.cmd('network cross-region-lb frontend-ip create -g {rg} --lb-name lb1 -n ipconfig1 --public-ip-address publicip2')
        self.cmd('network cross-region-lb frontend-ip list -g {rg} --lb-name lb1',
                 checks=self.check('length(@)', 2))
        self.cmd('network cross-region-lb frontend-ip update -g {rg} --lb-name lb1 -n ipconfig1 --public-ip-address publicip3')
        self.cmd('network cross-region-lb frontend-ip show -g {rg} --lb-name lb1 -n ipconfig1',
                 checks=self.check("publicIPAddress.contains(id, 'publicip3')", True))

        # test generic update
        self.kwargs['ip2_id'] = resource_id(subscription=self.get_subscription_id(), resource_group=self.kwargs['rg'], namespace='Microsoft.Network', type='publicIPAddresses', name='publicip2')
        self.cmd('network cross-region-lb frontend-ip update -g {rg} --lb-name lb1 -n ipconfig1 --set publicIPAddress.id="{ip2_id}"',
                 checks=self.check("publicIPAddress.contains(id, 'publicip2')", True))
        self.cmd('network cross-region-lb frontend-ip delete -g {rg} --lb-name lb1 -n ipconfig1')
        self.cmd('network cross-region-lb frontend-ip list -g {rg} --lb-name lb1',
                 checks=self.check('length(@)', 1))

    @ResourceGroupPreparer(name_prefix='cli_test_cross_region_lb_address_pool', location='eastus2')
    def test_network_cross_region_lb_address_pool(self, resource_group):

        self.kwargs.update({
            'lb': self.create_random_name('cross_region_lb', 24),
            'rg': resource_group
        })

        self.cmd('network cross-region-lb create -g {rg} -n {lb}')

        for i in range(1, 4):
            self.cmd('network cross-region-lb address-pool create -g {{rg}} --lb-name {{lb}} -n bap{}'.format(i),
                     checks=self.check('name', 'bap{}'.format(i)))
        self.cmd('network lb address-pool list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 4))
        self.cmd('network lb address-pool show -g {rg} --lb-name {lb} -n bap1',
                 checks=self.check('name', 'bap1'))
        self.cmd('network lb address-pool delete -g {rg} --lb-name {lb} -n bap1',
                 checks=self.is_empty())
        self.cmd('network lb address-pool list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 3))

    @ResourceGroupPreparer(name_prefix='cli_test_cross_region_lb_address_pool_addresses', location='eastus2')
    def test_network_cross_region_lb_address_pool_addresses(self, resource_group):

        self.kwargs.update({
            'regional_lb1': self.create_random_name('regional_lb', 24),
            'regional_lb2': self.create_random_name('regional_lb', 24),
            'lb': self.create_random_name('cross_region_lb', 24),
            'address_pool': self.create_random_name('address_pool', 24),
            'backend_address1': self.create_random_name('backend_address', 24),
            'backend_address2': self.create_random_name('backend_address', 24),
            'rg': resource_group,
            'lb_address_pool_file_path': os.path.join(TEST_DIR, 'test-cross-region-lb-address-pool-config.json')
        })

        regional_lb_frontend_ip_address1 = self.cmd('network lb create -n {regional_lb1} -g {rg} --sku Standard').get_output_in_json()['loadBalancer']['frontendIPConfigurations'][0]['id']
        regional_lb_frontend_ip_address2 = self.cmd('network lb create -n {regional_lb2} -g {rg} --sku Standard').get_output_in_json()['loadBalancer']['frontendIPConfigurations'][0]['id']

        self.kwargs.update({
            'regional_lb_frontend_ip_address1': regional_lb_frontend_ip_address1,
            'regional_lb_frontend_ip_address2': regional_lb_frontend_ip_address2
        })
        self.cmd('network cross-region-lb create -g {rg} -n {lb}')

        self.cmd('network cross-region-lb address-pool create -g {rg} --lb-name {lb} -n {address_pool} '
                 '--backend-address name={backend_address1} frontend-ip-address={regional_lb_frontend_ip_address1} '
                 '--admin-state Up',
                 checks=[self.check('name', self.kwargs['address_pool']),
                         self.check('loadBalancerBackendAddresses[0].adminState', 'Up'),
                         ])

        self.cmd('network cross-region-lb address-pool update -g {rg} --lb-name {lb} -n {address_pool} '
                 '--backend-address name={backend_address1} frontend-ip-address={regional_lb_frontend_ip_address1} admin-state=Down',
                 checks=[self.check('name', self.kwargs['address_pool']),
                         self.check('loadBalancerBackendAddresses[0].adminState', 'Down'),
                         ])

        self.cmd('network cross-region-lb address-pool address add -g {rg} --lb-name {lb} --pool-name {address_pool} --name {backend_address2} --frontend-ip-address {regional_lb_frontend_ip_address2} --admin-state Down',
                 checks=[self.check('name', self.kwargs['address_pool']),
                         self.check('loadBalancerBackendAddresses[1].adminState', 'Down'),
                         ])

        self.cmd(
            'network cross-region-lb address-pool address update -g {rg} --lb-name {lb} --pool-name {address_pool} --name {backend_address2} --admin-state Up',
            checks=[self.check('name', self.kwargs['address_pool']),
                    self.check('loadBalancerBackendAddresses[1].adminState', 'Up'),
                    ])

        self.cmd('network cross-region-lb address-pool address remove -g {rg} --lb-name {lb} --pool-name {address_pool} --name {backend_address2}')

        self.cmd('network cross-region-lb address-pool address list -g {rg} --lb-name {lb} --pool-name {address_pool}', checks=self.check('length(@)', 1))

        self.cmd('network cross-region-lb address-pool list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 2))
        self.cmd('network cross-region-lb address-pool show -g {rg} --lb-name {lb} -n {address_pool}',
                 checks=self.check('name', self.kwargs['address_pool']))
        self.cmd('network cross-region-lb address-pool address remove -g {rg} --lb-name {lb} --pool-name {address_pool} --name {backend_address1}')
        self.cmd('network cross-region-lb address-pool delete -g {rg} --lb-name {lb} -n {address_pool}',
                 checks=self.is_empty())
        self.cmd('network cross-region-lb address-pool list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 1))

    @ResourceGroupPreparer(name_prefix='cli_test_cross_region_lb_rules')
    def test_network_cross_region_lb_rules(self, resource_group):

        self.kwargs['lb'] = 'lb1'
        self.cmd('network cross-region-lb create -g {rg} -n {lb}')

        self.cmd('network cross-region-lb rule create -g {rg} --lb-name {lb} -n rule2 --frontend-port 60 --backend-port 60 --protocol tcp',
                 checks=[
                     self.check('enableTcpReset', False),
                     self.check('idleTimeoutInMinutes', 4)])
        self.cmd('network cross-region-lb address-pool create -g {rg} --lb-name {lb} -n bap1')
        self.cmd('network cross-region-lb address-pool create -g {rg} --lb-name {lb} -n bap2')
        self.cmd('network cross-region-lb rule create -g {rg} --lb-name {lb} -n rule1 --frontend-ip-name LoadBalancerFrontEnd --frontend-port 40 --backend-pool-name bap1 --backend-port 40 --protocol tcp')

        self.cmd('network cross-region-lb rule list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 2))
        self.cmd('network cross-region-lb rule update -g {rg} --lb-name {lb} -n rule1 --floating-ip true --load-distribution sourceip --protocol udp')
        self.cmd('network cross-region-lb rule update -g {rg} --lb-name {lb} -n rule2 --backend-pool-name bap2 --load-distribution sourceipprotocol')
        self.cmd('network cross-region-lb rule show -g {rg} --lb-name {lb} -n rule1', checks=[
            self.check('enableFloatingIP', True),
            self.check('idleTimeoutInMinutes', 4),
            self.check('loadDistribution', 'SourceIP'),
            self.check('protocol', 'Udp')
        ])

        self.cmd('network cross-region-lb rule show -g {rg} --lb-name {lb} -n rule2', checks=[
            self.check("backendAddressPool.contains(id, 'bap2')", True),
            self.check('loadDistribution', 'SourceIPProtocol')
        ])
        self.cmd('network cross-region-lb rule delete -g {rg} --lb-name {lb} -n rule1')
        self.cmd('network cross-region-lb rule delete -g {rg} --lb-name {lb} -n rule2')
        self.cmd('network cross-region-lb rule list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 0))


class NetworkLoadBalancerScenarioTest(ScenarioTest):

    @AllowLargeResponse()
    @ResourceGroupPreparer(name_prefix='cli_test_load_balancer', location='eastus2')
    def test_network_lb(self, resource_group):

        self.kwargs.update({
            'lb': 'lb',
            'rt': 'Microsoft.Network/loadBalancers',
            'vnet': 'mytestvnet',
            'pri_ip': '10.0.0.15',
            'pub_ip': 'publicip4'
        })

        # test lb create with min params (new ip)
        self.cmd('network lb create -n {lb}1 -g {rg}', checks=[
            self.check('loadBalancer.frontendIPConfigurations[0].properties.privateIPAllocationMethod', 'Dynamic'),
            self.check('loadBalancer.frontendIPConfigurations[0].resourceGroup', '{rg}')
        ])

        # test internet facing load balancer with new static public IP
        self.cmd('network lb create -n {lb}2 -g {rg} --public-ip-address-allocation static --tags foo=doo')
        self.cmd('network public-ip show -g {rg} -n PublicIP{lb}2', checks=[
            self.check('publicIPAllocationMethod', 'Static'),
            self.check('tags.foo', 'doo')
        ])

        # test internal load balancer create (existing subnet ID)
        self.kwargs['subnet_id'] = self.cmd('network vnet create -n {vnet} -g {rg} --subnet-name default').get_output_in_json()['newVNet']['subnets'][0]['id']
        self.cmd('network lb create -n {lb}3 -g {rg} --subnet {subnet_id} --private-ip-address {pri_ip}', checks=[
            self.check('loadBalancer.frontendIPConfigurations[0].properties.privateIPAllocationMethod', 'Static'),
            self.check('loadBalancer.frontendIPConfigurations[0].properties.privateIPAddress', '{pri_ip}'),
            self.check('loadBalancer.frontendIPConfigurations[0].resourceGroup', '{rg}'),
            self.check("loadBalancer.frontendIPConfigurations[0].properties.subnet.id", '{subnet_id}')
        ])

        # test internet facing load balancer with existing public IP (by name)
        self.cmd('network public-ip create -n {pub_ip} -g {rg}')
        self.cmd('network lb create -n {lb}4 -g {rg} --public-ip-address {pub_ip}', checks=[
            self.check('loadBalancer.frontendIPConfigurations[0].properties.privateIPAllocationMethod', 'Dynamic'),
            self.check('loadBalancer.frontendIPConfigurations[0].resourceGroup', '{rg}'),
            self.check("loadBalancer.frontendIPConfigurations[0].properties.publicIPAddress.contains(id, '{pub_ip}')", True)
        ])

        self.cmd('network lb list', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?type == '{rt}']) == length(@)", True)
        ])
        self.cmd('network lb list --resource-group {rg}', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?type == '{rt}']) == length(@)", True),
            self.check("length([?resourceGroup == '{rg}']) == length(@)", True)
        ])
        self.cmd('network lb show --resource-group {rg} --name {lb}1', checks=[
            self.check('type(@)', 'object'),
            self.check('type', '{rt}'),
            self.check('resourceGroup', '{rg}'),
            self.check('name', '{lb}1')
        ])
        self.cmd('network lb delete --resource-group {rg} --name {lb}1')
        # Expecting no results as we just deleted the only lb in the resource group
        self.cmd('network lb list --resource-group {rg}',
                 checks=self.check('length(@)', 3))

    @live_only()
    @AllowLargeResponse()
    @ResourceGroupPreparer(name_prefix='cli_test_network_lb_with_cross_subscription_id_', location='eastus2euap')
    @ResourceGroupPreparer(name_prefix='cli_test_network_lb_with_cross_subscription_id_', location='eastus2euap',
                           parameter_name='aux_resource_group', subscription=AUX_SUBSCRIPTION)
    def test_network_lb_with_cross_subscription_id(self, resource_group, aux_resource_group):

        self.kwargs.update({
            'rg': resource_group,
            'rg2': aux_resource_group,
            'aux_sub': AUX_SUBSCRIPTION,
            'lb': self.create_random_name("lb", 12),
            'vnet': self.create_random_name("vnet", 12),
            "subnet": self.create_random_name("subnet", 12),
            'lb2': self.create_random_name("lb2", 12),
            'publicip': self.create_random_name("publicip", 12),
        })
        
        vnet = self.cmd('network vnet create -n {vnet} -g {rg2} --subnet-name {subnet} --subscription {aux_sub}', checks=[
            self.check('newVNet.name', '{vnet}'),
        ]).get_output_in_json()

        self.cmd('network vnet subnet update -n {subnet} -g {rg2} --vnet-name {vnet} --default-outbound-access false --subscription {aux_sub}')

        self.kwargs['vnet_id'] = vnet['newVNet']['id']
        self.kwargs['subnet_id'] = vnet['newVNet']['subnets'][0]['id']

        self.cmd('network lb create -g {rg} -n {lb} --subnet {subnet_id} --sku Standard', checks=[
            self.check('loadBalancer.frontendIPConfigurations[0].resourceGroup', '{rg}'),
        ])

        public_ip_address_id = self.cmd('network public-ip create -g {rg2} -n {publicip} --subscription {aux_sub} --ip-tags FirstPartyUsage=/NonProd', checks=[
            self.check('publicIp.name', '{publicip}')
        ]).get_output_in_json()['publicIp']['id']

        self.kwargs['publicip_id'] = public_ip_address_id

        self.cmd('network lb create -g {rg} -n {lb2} --public-ip-address {publicip_id} --sku Standard', checks=[
            self.check('loadBalancer.frontendIPConfigurations[0].resourceGroup', '{rg}'),
            self.check('loadBalancer.frontendIPConfigurations[0].properties.publicIPAddress.id', '{publicip_id}'),
        ])


class NetworkLoadBalancerIpConfigScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_load_balancer_ip_config', location='westus')
    def test_network_load_balancer_ip_config(self, resource_group):

        for i in range(1, 4):  # create 3 public IPs to use for the test
            self.cmd('network public-ip create -g {{rg}} -n publicip{}'.format(i))

        # create internet-facing LB with public IP (lb1)
        self.cmd('network lb create -g {rg} -n lb1 --public-ip-address publicip1')

        # create internal LB (lb2)
        self.cmd('network vnet create -g {rg} -n vnet1 --subnet-name subnet1')
        self.cmd('network vnet subnet create -g {rg} --vnet-name vnet1 -n subnet2 --address-prefix 10.0.1.0/24 --default-outbound false')
        self.cmd('network lb create -g {rg} -n lb2 --subnet subnet1 --vnet-name vnet1')

        # Test frontend IP configuration for internet-facing LB
        self.cmd('network lb frontend-ip create -g {rg} --lb-name lb1 -n ipconfig1 --public-ip-address publicip2')
        self.cmd('network lb frontend-ip list -g {rg} --lb-name lb1',
                 checks=self.check('length(@)', 2))
        self.cmd('network lb frontend-ip update -g {rg} --lb-name lb1 -n ipconfig1 --public-ip-address publicip3')
        self.cmd('network lb frontend-ip show -g {rg} --lb-name lb1 -n ipconfig1',
                 checks=self.check("publicIPAddress.contains(id, 'publicip3')", True))

        # test generic update
        self.kwargs['ip2_id'] = resource_id(subscription=self.get_subscription_id(), resource_group=self.kwargs['rg'], namespace='Microsoft.Network', type='publicIPAddresses', name='publicip2')
        self.cmd('network lb frontend-ip update -g {rg} --lb-name lb1 -n ipconfig1 --public-ip-address "{ip2_id}"',
                 checks=self.check("publicIPAddress.contains(id, 'publicip2')", True))
        self.cmd('network lb frontend-ip delete -g {rg} --lb-name lb1 -n ipconfig1')
        self.cmd('network lb frontend-ip list -g {rg} --lb-name lb1',
                 checks=self.check('length(@)', 1))

        # Test frontend IP configuration for internal LB
        self.cmd('network lb frontend-ip create -g {rg} --lb-name lb2 -n ipconfig2 --vnet-name vnet1 --subnet subnet1 --private-ip-address 10.0.0.99')
        self.cmd('network lb frontend-ip list -g {rg} --lb-name lb2',
                 checks=self.check('length(@)', 2))
        self.cmd('network lb frontend-ip update -g {rg} --lb-name lb2 -n ipconfig2 --subnet subnet2 --vnet-name vnet1 --private-ip-address 10.0.1.100')
        self.cmd('network lb frontend-ip show -g {rg} --lb-name lb2 -n ipconfig2',
                 checks=self.check("subnet.contains(id, 'subnet2')", True))


class NetworkLoadBalancerOutboundRulesScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='test_network_lb_outbound_rules', location='eastus2')
    def test_network_load_balancer_outbound_rules(self, resource_group, resource_group_location):

        self.kwargs.update({
            'loc': resource_group_location,
            'lb': 'lb1',
            'prefix': 'prefix1',
            'frontend1': 'LoadBalancerFrontEnd',
            'frontend2': 'prefixFrontEnd',
            'backend': 'lb1bepool',
            'rule1': 'rule1',
            'rule2': 'rule2'
        })

        self.cmd('network lb create -g {rg} -n {lb} --sku Standard')
        self.cmd('network public-ip prefix create -g {rg} -n {prefix} --length 30')
        self.cmd('network lb frontend-ip create -g {rg} --lb-name {lb} -n {frontend2} --public-ip-prefix {prefix}')
        self.cmd('network lb outbound-rule create -g {rg} --lb-name {lb} -n {rule1} --address-pool {backend} --enable-tcp-reset --frontend-ip-configs {frontend1} --outbound-ports 512 --protocol Tcp', checks=[
            self.check('enableTcpReset', True),
            self.check('protocol', 'Tcp'),
            self.check('allocatedOutboundPorts', 512),
            self.check("contains(backendAddressPool.id, '{backend}')", True),
            self.check("contains(frontendIPConfigurations[0].id, '{frontend1}')", True)
        ])
        self.cmd('network lb outbound-rule create -g {rg} --lb-name {lb} -n {rule2} --address-pool {backend} --frontend-ip-configs {frontend2} --idle-timeout 20 --protocol all', checks=[
            self.check('idleTimeoutInMinutes', 20),
            self.check("contains(backendAddressPool.id, '{backend}')", True),
            self.check("contains(frontendIPConfigurations[0].id, '{frontend2}')", True)
        ])
        self.cmd('network lb outbound-rule update -g {rg} --lb-name {lb} -n {rule2} --idle-timeout 25',
                 checks=self.check('idleTimeoutInMinutes', 25))
        self.cmd('network lb outbound-rule list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 2))
        self.cmd('network lb outbound-rule show -g {rg} --lb-name {lb} -n {rule1}', checks=[
            self.check('enableTcpReset', True),
            self.check('protocol', 'Tcp'),
            self.check('allocatedOutboundPorts', 512),
            self.check("contains(backendAddressPool.id, '{backend}')", True),
            self.check("contains(frontendIPConfigurations[0].id, '{frontend1}')", True)
        ])
        self.cmd('network lb outbound-rule delete -g {rg} --lb-name {lb} -n {rule1}')
        self.cmd('network lb outbound-rule list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 1))


class NetworkLoadBalancerSubresourceScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_lb_nat_rules', location='eastus2')
    def test_network_lb_nat_rules(self, resource_group):

        self.kwargs['lb'] = 'lb1'
        self.cmd('network lb create -g {rg} -n {lb}')

        for count in range(1, 3):
            self.cmd('network lb inbound-nat-rule create -g {{rg}} --lb-name {{lb}} -n rule{0} --protocol tcp --frontend-port {0} --backend-port {0} --frontend-ip-name LoadBalancerFrontEnd'.format(count))
        self.cmd('network lb inbound-nat-rule create -g {rg} --lb-name {lb} -n rule3 --protocol tcp --frontend-port 3 --backend-port 3')
        self.cmd('network lb inbound-nat-rule list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 3))
        self.cmd('network lb inbound-nat-rule update -g {rg} --lb-name {lb} -n rule1 --floating-ip true --idle-timeout 10')
        self.cmd('network lb inbound-nat-rule show -g {rg} --lb-name {lb} -n rule1', checks=[
            self.check('enableFloatingIP', True),
            self.check('idleTimeoutInMinutes', 10)
        ])
        # test generic update
        self.cmd('network lb inbound-nat-rule update -g {rg} --lb-name {lb} -n rule1 --set idleTimeoutInMinutes=5',
                 checks=self.check('idleTimeoutInMinutes', 5))

        for count in range(1, 4):
            self.cmd('network lb inbound-nat-rule delete -g {{rg}} --lb-name {{lb}} -n rule{}'.format(count))
        self.cmd('network lb inbound-nat-rule list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 0))

    @ResourceGroupPreparer(name_prefix='cli_test_lb_nat_rules_v2', location='eastus2')
    def test_network_lb_nat_rules_v2(self, resource_group):
        self.kwargs['lb'] = 'lb1'
        self.cmd('network lb create -g {rg} -n {lb} --sku Standard')

        self.cmd('network lb inbound-nat-rule create -g {rg} --lb-name {lb} -n rule3 --protocol tcp  --backend-port 3 '
                 '--frontend-port-range-start 0 --frontend-port-range-end 3', checks=[
                 self.check('name', 'rule3'),
                 self.check('frontendPortRangeStart', 0),
                 self.check('frontendPortRangeEnd', 3)])
        self.cmd('network lb inbound-nat-rule update -g {rg} --lb-name {lb} -n rule3 --floating-ip true --idle-timeout 10 --frontend-port-range-end 5',
                 checks=self.check('frontendPortRangeEnd', 5))
        self.cmd('network lb inbound-nat-rule delete -g {rg} --lb-name {lb} -n rule3')

    @ResourceGroupPreparer(name_prefix='cli_test_lb_nat_rules_v3', location='eastus2euap')
    def test_network_lb_nat_rules_v3(self, resource_group):
        self.kwargs.update({
            'lb': 'lb1',
            'backend': 'lb1bepool',
        })

        self.cmd('network lb create -g {rg} -n {lb} --sku Standard')

        # test lb inbound-nat-rule create with new param --backend-pool-name
        self.cmd('network lb inbound-nat-rule create -g {rg} --lb-name {lb} -n rule3 --protocol tcp --backend-port 30 '
                 '--frontend-port-range-start 0 --frontend-port-range-end 3 --backend-pool-name {backend}', checks=[
            self.check('name', 'rule3'),
            self.check('frontendPortRangeStart', 0),
            self.check('frontendPortRangeEnd', 3),
            self.check("contains(backendAddressPool.id, '{backend}')", True)])
        self.cmd(
            'network lb inbound-nat-rule update -g {rg} --lb-name {lb} -n rule3 --floating-ip true --idle-timeout 10 --frontend-port-range-end 5',
            checks=self.check('frontendPortRangeEnd', 5))
        self.cmd('network lb inbound-nat-rule delete -g {rg} --lb-name {lb} -n rule3')

    @ResourceGroupPreparer(name_prefix='cli_test_lb_nat_pools', location='eastus2')
    def test_network_lb_nat_pools(self, resource_group):

        self.kwargs['lb'] = 'lb1'
        self.cmd('network lb create -g {rg} -n {lb}')

        for count in range(1000, 4000, 1000):
            self.cmd('network lb inbound-nat-pool create -g {{rg}} --lb-name {{lb}} -n rule{0} --protocol tcp --frontend-port-range-start {0}  --frontend-port-range-end {1} --backend-port {0}'.format(count, count + 999))
        self.cmd('network lb inbound-nat-pool list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 3))
        self.cmd('network lb inbound-nat-pool update -g {rg} --lb-name {lb} -n rule1000 --protocol udp --backend-port 50 --floating-ip --idle-timeout 20')
        self.cmd('network lb inbound-nat-pool show -g {rg} --lb-name {lb} -n rule1000', checks=[
            self.check('protocol', 'Udp'),
            self.check('backendPort', 50),
            self.check('enableFloatingIP', True),
            self.check('idleTimeoutInMinutes', 20)
        ])
        # test generic update
        self.cmd('network lb inbound-nat-pool update -g {rg} --lb-name {lb} -n rule1000 --set protocol=Tcp',
                 checks=self.check('protocol', 'Tcp'))

        for count in range(1000, 4000, 1000):
            self.cmd('network lb inbound-nat-pool delete -g {{rg}} --lb-name {{lb}} -n rule{}'.format(count))
        self.cmd('network lb inbound-nat-pool list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 0))

    @ResourceGroupPreparer(name_prefix='cli_test_lb_address_pool', location='eastus2')
    def test_network_lb_address_pool(self, resource_group):

        self.kwargs['lb'] = 'lb1'
        self.cmd('network lb create -g {rg} -n {lb}')

        for i in range(1, 4):
            self.cmd('network lb address-pool create -g {{rg}} --lb-name {{lb}} -n bap{}'.format(i),
                     checks=self.check('name', 'bap{}'.format(i)))
        self.cmd('network lb address-pool list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 4))
        self.cmd('network lb address-pool show -g {rg} --lb-name {lb} -n bap1',
                 checks=self.check('name', 'bap1'))
        self.cmd('network lb address-pool delete -g {rg} --lb-name {lb} -n bap1',
                 checks=self.is_empty())
        self.cmd('network lb address-pool list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 3))

    @ResourceGroupPreparer(name_prefix='cli_test_lb_address_pool_with_sync_mode', location='eastus2')
    def test_network_lb_address_pool_with_sync_mode(self, resource_group):

        self.kwargs.update({
            'lb': self.create_random_name('lb', 10),
            'ap1': self.create_random_name('ap1', 10),
            'ap2': self.create_random_name('ap2', 10),
            'vnet': self.create_random_name('vnet', 10),
        })
        self.cmd('network lb create -g {rg} -n {lb}')
        self.cmd('network vnet create -g {rg} -n {vnet}')

        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n {ap1} --sync-mode Manual --vnet {vnet}')
        self.cmd('network lb address-pool show -g {rg} --lb-name {lb} -n {ap1}',
                 checks=[self.check('name', '{ap1}'),
                         self.check('syncMode', 'Manual')])
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n {ap2}')
        self.cmd('network lb address-pool update -g {rg} --lb-name {lb} -n {ap2} --sync-mode Automatic --vnet {vnet}',
                 checks=self.check('syncMode', 'Automatic'))

        self.cmd('network lb address-pool delete -g {rg} --lb-name {lb} -n {ap1}',
                 checks=self.is_empty())
        self.cmd('network lb address-pool delete -g {rg} --lb-name {lb} -n {ap2}',
                 checks=self.is_empty())

    @ResourceGroupPreparer(name_prefix='cli_test_lb_address_pool_addresses', location='eastus2')
    def test_network_lb_address_pool_addresses(self, resource_group):

        self.kwargs.update({
            'lb': 'lb1',
            'vnet': 'clitestvnet',
            'nic': 'clitestnic',
            'rg': resource_group,
            'lb_address_pool_file_path': os.path.join(TEST_DIR, 'test-address-pool-config.json'),
            'subnet_name': 'subnetx'
        })
        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name subnet1')
        self.cmd('network vnet subnet create -g {rg} -n {subnet_name} --vnet-name {vnet} --address-prefixes 10.0.1.0/24 --default-outbound false')
        self.cmd('network nic create -g {rg} -n {nic} --subnet subnet1 --vnet-name {vnet}')
        self.cmd('network lb create -g {rg} -n {lb} --sku Standard')

        self.kwargs['subnet'] = self.cmd('network vnet show -g {rg} -n {vnet}').get_output_in_json()['subnets'][0]['id']

        # create with vnet
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n bap1 --vnet {vnet} '
                 '--backend-address name=addr1 ip-address=10.0.0.1 '
                 '--backend-address name=addr2 ip-address=10.0.0.2 '
                 '--backend-address name=addr3 ip-address=10.0.0.3 '
                 '--drain-period 10',
                 checks=self.check('name', 'bap1'))

        # create with subnet
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n bap2 --vnet {vnet} --admin-state None '
                 '--backend-address name=addr1 ip-address=10.0.0.1 subnet={subnet} '
                 '--backend-address name=addr2 ip-address=10.0.1.1 subnet={subnet_name} '
                 '--backend-address name=addr3 ip-address=10.0.0.3 subnet={subnet} '
                 '--drain-period 10',
                 checks=[
                     self.check('name', 'bap2'),
                     self.check('drainPeriodInSeconds', 10),
                     self.check('loadBalancerBackendAddresses[0].adminState', 'None'),
                     self.check('loadBalancerBackendAddresses[1].adminState', 'None'),
                     self.check('loadBalancerBackendAddresses[2].adminState', 'None')
                 ])

        # update backend pool
        self.cmd('network lb address-pool update -g {rg} --lb-name {lb} -n bap2 --vnet {vnet} --admin-state None '
                 '--backend-address name=addr1 ip-address=10.0.0.3 subnet={subnet} '
                 '--backend-address name=addr2 ip-address=10.0.1.2 subnet={subnet_name} '
                 '--backend-address name=addr3 ip-address=10.0.0.5 subnet={subnet} '
                 '--drain-period 20',
                 checks=[
                     self.check('loadBalancerBackendAddresses[0].ipAddress', '10.0.0.3'),
                     self.check('loadBalancerBackendAddresses[1].ipAddress', '10.0.1.2'),
                     self.check('loadBalancerBackendAddresses[2].ipAddress', '10.0.0.5'),
                     self.check('drainPeriodInSeconds', 20),
                     self.check('loadBalancerBackendAddresses[0].adminState', 'None'),
                     self.check('loadBalancerBackendAddresses[1].adminState', 'None'),
                     self.check('loadBalancerBackendAddresses[2].adminState', 'None')
                 ])

        self.cmd('network lb address-pool delete -g {rg} --lb-name {lb} -n bap2 ')

        self.cmd('network lb address-pool address add -g {rg} --lb-name {lb} --pool-name bap1 --name addr6 --vnet {vnet} --ip-address 10.0.0.6 --admin-state None',
                 checks=[
                     self.check('name', 'bap1'),
                     self.check('loadBalancerBackendAddresses[3].adminState', 'None')
                 ])

        self.cmd('network lb address-pool address remove -g {rg} --lb-name {lb} --pool-name bap1 --name addr2')

        self.cmd('network lb address-pool address list -g {rg} --lb-name {lb} --pool-name bap1', checks=self.check('length(@)', '3'))

        self.cmd('network lb address-pool list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 2))
        self.cmd('network lb address-pool show -g {rg} --lb-name {lb} -n bap1',
                 checks=self.check('name', 'bap1'))
        self.cmd('network lb address-pool delete -g {rg} --lb-name {lb} -n bap1',
                 checks=self.is_empty())
        self.cmd('network lb address-pool list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 1))

        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n bap1 --vnet {vnet} '
                 '--backend-addresses @"{lb_address_pool_file_path}"',
                 checks=self.check('name', 'bap1'))
        self.cmd('network lb address-pool address list -g {rg} --lb-name {lb} --pool-name bap1', checks=self.check('length(@)', '2'))
        self.cmd('network lb address-pool delete -g {rg} --lb-name {lb} -n bap1', checks=self.is_empty())
        self.cmd('network lb address-pool list -g {rg} --lb-name {lb}', checks=self.check('length(@)', 1))
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n bap1 --vnet {vnet}', checks=self.check('name', 'bap1'))

        self.cmd('network lb address-pool address add -g {rg} --lb-name {lb} --pool-name bap1 --name addr6 --vnet {vnet} --ip-address 10.0.0.6', checks=self.check('name', 'bap1'))

        self.cmd('network lb address-pool address list -g {rg} --lb-name {lb} --pool-name bap1', checks=self.check('length(@)', '1'))

        self.cmd('network lb address-pool address add -g {rg} --lb-name {lb} --pool-name bap1 --name addr7 --subnet {subnet} --ip-address 10.0.0.7', checks=self.check('name', 'bap1'))

        self.cmd('network lb address-pool address add -g {rg} --lb-name {lb} --pool-name bap1 --name addr8 --vnet {vnet} --subnet {subnet_name} --ip-address 10.0.1.3', checks=self.check('name', 'bap1'))

        self.cmd('network lb address-pool address list -g {rg} --lb-name {lb} --pool-name bap1', checks=self.check('length(@)', '3'))

    @ResourceGroupPreparer(name_prefix='cli_test_lb_probes', location='eastus2')
    def test_network_lb_probes(self, resource_group):

        self.kwargs['lb'] = 'lb1'
        self.kwargs['lb2'] = 'lb2'
        self.kwargs['probe5'] = 'probe5'
        self.cmd('network lb create -g {rg} -n {lb}')

        for i in range(1, 4):
            self.cmd('network lb probe create -g {{rg}} --lb-name {{lb}} -n probe{0} --port {0} --protocol http --path "/test{0}"'.format(i))
        self.cmd('network lb probe list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 3))
        self.cmd('network lb probe update -g {rg} --lb-name {lb} -n probe1 --interval 20 --threshold 5')
        self.cmd('network lb probe update -g {rg} --lb-name {lb} -n probe2 --protocol tcp --path ""')
        self.cmd('network lb probe show -g {rg} --lb-name {lb} -n probe1', checks=[
            self.check('intervalInSeconds', 20),
            self.check('numberOfProbes', 5)
        ])

        self.cmd('network lb probe show -g {rg} --lb-name {lb} -n probe2', checks=[
            self.check('protocol', 'Tcp'),
            self.check('path', None)
        ])
        self.cmd('network lb probe delete -g {rg} --lb-name {lb} -n probe3')
        self.cmd('network lb probe list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 2))

        # test standard LB supports https probe
        self.cmd('network lb create -g {rg} -n {lb2} --sku standard')
        self.cmd('network lb probe create -g {rg} --lb-name {lb2} -n probe1 --port 443 --protocol https --path "/test1"')
        self.cmd('network lb probe list -g {rg} --lb-name {lb2}', checks=self.check('[0].protocol', 'Https'))

        # test --probe-threshold parameter
        self.cmd('network lb probe create -g {rg} --lb-name {lb2} -n {probe5} --port 443 --protocol https --path "/test1" --probe-threshold 5', checks=self.check('probeThreshold', 5))
        self.cmd('network lb probe show -g {rg} --lb-name {lb2} -n {probe5}', checks=self.check('probeThreshold', 5))
        self.cmd('network lb probe update -g {rg} --lb-name {lb2} -n {probe5} --port 443 --protocol https --path "/test1" --probe-threshold 6', checks=self.check('probeThreshold', 6))
        self.cmd('network lb probe show -g {rg} --lb-name {lb2} -n {probe5}', checks=self.check('probeThreshold', 6))
        self.cmd('network lb probe list -g {rg} --lb-name {lb2}', checks=[
            self.check('length(@)', 2),
            self.check('[1].probeThreshold', 6)
        ])

    @ResourceGroupPreparer(name_prefix='cli_test_lb_rules', location='eastus2')
    def test_network_lb_rules(self, resource_group):

        self.kwargs['lb'] = 'lb1'
        self.cmd('network lb create -g {rg} -n {lb}')

        self.cmd('network lb rule create -g {rg} --lb-name {lb} -n rule2 --frontend-port 60 --backend-port 60 --protocol tcp')
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n bap1')
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n bap2')
        self.cmd('network lb rule create -g {rg} --lb-name {lb} -n rule1 --frontend-ip-name LoadBalancerFrontEnd --frontend-port 40 --backend-pool-name bap1 --backend-port 40 --protocol tcp')

        self.cmd('network lb rule list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 2))
        self.cmd('network lb rule update -g {rg} --lb-name {lb} -n rule1 --floating-ip true --idle-timeout 20 --load-distribution sourceip --protocol udp')
        self.cmd('network lb rule update -g {rg} --lb-name {lb} -n rule2 --backend-pool-name bap2 --load-distribution sourceipprotocol')
        self.cmd('network lb rule show -g {rg} --lb-name {lb} -n rule1', checks=[
            self.check('enableFloatingIP', True),
            self.check('idleTimeoutInMinutes', 20),
            self.check('loadDistribution', 'SourceIP'),
            self.check('protocol', 'Udp')
        ])
        # test generic update
        self.cmd('network lb rule update -g {rg} --lb-name {lb} -n rule1 --set idleTimeoutInMinutes=5',
                 checks=self.check('idleTimeoutInMinutes', 5))

        self.cmd('network lb rule show -g {rg} --lb-name {lb} -n rule2', checks=[
            self.check("backendAddressPool.contains(id, 'bap2')", True),
            self.check('loadDistribution', 'SourceIPProtocol')
        ])
        self.cmd('network lb rule delete -g {rg} --lb-name {lb} -n rule1')
        self.cmd('network lb rule delete -g {rg} --lb-name {lb} -n rule2')
        self.cmd('network lb rule list -g {rg} --lb-name {lb}',
                 checks=self.check('length(@)', 0))

    @ResourceGroupPreparer(name_prefix="cli_test_network_lb_port_mapping_")
    def test_network_lb_port_mapping(self):
        self.kwargs.update({
            "lb": "test-lb",
            "rule": "test-nat",
            "pool": "test-pool",
            "start": 3389,
            "end": 4000,
            "vnet": "test-vnet",
            "subnet": "test-subnet",
            "ip": "10.0.0.1",
            "address": "test-address",
        })

        # prepare backend address pool
        self.cmd("network lb create -n {lb} -g {rg} --sku standard")
        self.cmd("network lb address-pool create -n {pool} -g {rg} --lb-name {lb}")
        self.cmd("network vnet create -n {vnet} -g {rg} --subnet-name {subnet}")
        self.cmd(
            "network lb address-pool address add -n {address} -g {rg} --lb-name {lb} --pool-name {pool} "
            "--vnet {vnet} --ip-address {ip}"
        )
        self.cmd(
            "network lb inbound-nat-rule create -n {rule} -g {rg} --lb-name {lb} --backend-pool-name {pool} "
            "--backend-port {start} --frontend-port-range-start {start} --frontend-port-range-end {end} --protocol tcp"
        )

        self.cmd(
            "network lb list-mapping -n {lb} -g {rg} --backend-pool-name {pool} --request ip={ip}",
            checks=[
                self.check("inboundNatRulePortMappings[0].inboundNatRuleName", "{rule}"),
                self.check("inboundNatRulePortMappings[0].backendPort", self.kwargs["start"]),
                self.check("inboundNatRulePortMappings[0].frontendPort", self.kwargs["start"]),
                self.check("inboundNatRulePortMappings[0].protocol", "Tcp"),
            ]
        )


class NetworkLocalGatewayScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='local_gateway_scenario')
    def test_network_local_gateway(self, resource_group):

        self.kwargs.update({
            'lgw1': 'lgw1',
            'lgw2': 'lgw2',
            'rt': 'Microsoft.Network/localNetworkGateways'
        })
        self.cmd('network local-gateway create --resource-group {rg} --name {lgw1} --gateway-ip-address 10.1.1.1 --local-address-prefixes 10.0.1.0/24 --tags foo=doo')
        self.cmd('network local-gateway update --resource-group {rg} --name {lgw1} --tags foo=boo',
                 checks=self.check('tags.foo', 'boo'))
        self.cmd('network local-gateway show --resource-group {rg} --name {lgw1}', checks=[
            self.check('type', '{rt}'),
            self.check('resourceGroup', '{rg}'),
            self.check('name', '{lgw1}')])

        self.cmd('network local-gateway create --resource-group {rg} --name {lgw2} --gateway-ip-address 10.1.1.2 --local-address-prefixes 10.0.2.0/24',
                 checks=self.check('localNetworkAddressSpace.addressPrefixes[0]', '10.0.2.0/24'))

        self.cmd('network local-gateway list --resource-group {rg}',
                 checks=self.check('length(@)', 2))

        self.cmd('network local-gateway delete --resource-group {rg} --name {lgw1}')
        self.cmd('network local-gateway list --resource-group {rg}',
                 checks=self.check('length(@)', 1))


class NetworkNicScenarioTest(ScenarioTest):

    @AllowLargeResponse()
    @ResourceGroupPreparer(name_prefix='cli_test_nic_scenario', location='eastus2')
    def test_network_nic(self, resource_group):

        self.kwargs.update({
            'nic': 'cli-test-nic',
            'rt': 'Microsoft.Network/networkInterfaces',
            'subnet': 'mysubnet',
            'vnet': 'myvnet',
            'nsg1': 'mynsg',
            'nsg2': 'myothernsg',
            'lb': 'mylb',
            'pri_ip': '10.0.0.15',
            'pub_ip': 'publicip1'
        })

        self.kwargs['subnet_id'] = self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name {subnet}').get_output_in_json()['newVNet']['subnets'][0]['id']
        self.cmd('network nsg create -g {rg} -n {nsg1}')
        self.kwargs['nsg_id'] = self.cmd('network nsg show -g {rg} -n {nsg1}').get_output_in_json()['id']

        # test network nsg update
        self.cmd('network nsg update -g {rg} -n {nsg1} --set tags.CostCenter=MyBusinessGroup')
        self.cmd('network nsg show -g {rg} -n {nsg1}', checks=[
            self.check('tags.CostCenter', 'MyBusinessGroup')
        ])
        self.cmd('network nsg create -g {rg} -n {nsg2}')
        self.cmd('network public-ip create -g {rg} -n {pub_ip}')
        self.kwargs['pub_ip_id'] = self.cmd('network public-ip show -g {rg} -n {pub_ip}').get_output_in_json()['id']
        self.cmd('network lb create -g {rg} -n {lb}')
        self.cmd('network lb inbound-nat-rule create -g {rg} --lb-name {lb} -n rule1 --protocol tcp --frontend-port 100 --backend-port 100 --frontend-ip-name LoadBalancerFrontEnd')
        self.cmd('network lb inbound-nat-rule create -g {rg} --lb-name {lb} -n rule2 --protocol tcp --frontend-port 200 --backend-port 200 --frontend-ip-name LoadBalancerFrontEnd')
        self.kwargs['rule_ids'] = ' '.join(self.cmd('network lb inbound-nat-rule list -g {rg} --lb-name {lb} --query "[].id"').get_output_in_json())
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n bap1')
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n bap2')
        self.kwargs['address_pool_ids'] = ' '.join(self.cmd('network lb address-pool list -g {rg} --lb-name {lb} --query "[].id"').get_output_in_json())

        # create with minimum parameters
        self.cmd('network nic create -g {rg} -n {nic} --subnet {subnet} --vnet-name {vnet}', checks=[
            self.check('NewNIC.ipConfigurations[0].privateIPAllocationMethod', 'Dynamic'),
            self.check('NewNIC.provisioningState', 'Succeeded')
        ])
        # exercise optional parameters
        self.cmd('network nic create -g {rg} -n {nic} --subnet {subnet_id} --ip-forwarding --private-ip-address {pri_ip} --public-ip-address {pub_ip} --internal-dns-name test --dns-servers 100.1.2.3 --lb-address-pools {address_pool_ids} --lb-inbound-nat-rules {rule_ids} --accelerated-networking --tags foo=doo', checks=[
            self.check('NewNIC.ipConfigurations[0].privateIPAllocationMethod', 'Static'),
            self.check('NewNIC.ipConfigurations[0].privateIPAddress', '{pri_ip}'),
            self.check('NewNIC.enableIPForwarding', True),
            self.check('NewNIC.enableAcceleratedNetworking', True),
            self.check('NewNIC.provisioningState', 'Succeeded'),
            self.check('NewNIC.dnsSettings.internalDnsNameLabel', 'test'),
            self.check('length(NewNIC.dnsSettings.dnsServers)', 1)
        ])
        self.cmd('network lb list-nic -g {rg} -n {lb}', checks=[
            self.check('length(@)', 1)
        ])
        # exercise creating with NSG
        self.cmd('network nic create -g {rg} -n {nic} --subnet {subnet} --vnet-name {vnet} --network-security-group {nsg1}', checks=[
            self.check('NewNIC.ipConfigurations[0].privateIPAllocationMethod', 'Dynamic'),
            self.check('NewNIC.enableIPForwarding', False),
            self.check("NewNIC.networkSecurityGroup.contains(id, '{nsg1}')", True),
            self.check('NewNIC.provisioningState', 'Succeeded')
        ])
        # exercise creating with NSG and Public IP
        self.cmd('network nic create -g {rg} -n {nic} --subnet {subnet} --vnet-name {vnet} --network-security-group {nsg_id} --public-ip-address {pub_ip_id}', checks=[
            self.check('NewNIC.ipConfigurations[0].privateIPAllocationMethod', 'Dynamic'),
            self.check('NewNIC.enableIPForwarding', False),
            self.check("NewNIC.networkSecurityGroup.contains(id, '{nsg1}')", True),
            self.check('NewNIC.provisioningState', 'Succeeded')
        ])
        self.cmd('network nic list', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?contains(id, 'networkInterfaces')]) == length(@)", True)
        ])
        self.cmd('network nic list --resource-group {rg}', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?type == '{rt}']) == length(@)", True),
            self.check("length([?resourceGroup == '{rg}']) == length(@)", True)
        ])
        self.cmd('network nic show --resource-group {rg} --name {nic}', checks=[
            self.check('type(@)', 'object'),
            self.check('type', '{rt}'),
            self.check('resourceGroup', '{rg}'),
            self.check('name', '{nic}')
        ])
        self.cmd('network nic update -g {rg} -n {nic} --internal-dns-name noodle --ip-forwarding true --accelerated-networking false --dns-servers "[]" --network-security-group {nsg2}', checks=[
            self.check('enableIPForwarding', True),
            self.check('enableAcceleratedNetworking', False),
            self.check('dnsSettings.internalDnsNameLabel', 'noodle'),
            self.check('length(dnsSettings.dnsServers)', 0),
            self.check("networkSecurityGroup.contains(id, '{nsg2}')", True)
        ])
        # test generic update
        self.cmd('network nic update -g {rg} -n {nic} --set dnsSettings.internalDnsNameLabel=doodle --set enableIPForwarding=false', checks=[
            self.check('enableIPForwarding', False),
            self.check('dnsSettings.internalDnsNameLabel', 'doodle')
        ])

        self.cmd('network nic delete --resource-group {rg} --name {nic}')
        self.cmd('network nic list -g {rg}', checks=self.is_empty())

    @ResourceGroupPreparer(name_prefix='test_network_nic_auxiliary', location='eastus')
    def test_network_nic_auxiliary(self, resource_group):
        self.kwargs.update({
            'vnet': self.create_random_name('vnet', 10),
            'subnet': self.create_random_name('subnet', 10),
            'nic': self.create_random_name('nic', 10),
        })
        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name {subnet}')
        self.cmd('network nic create -g {rg} -n {nic} --vnet-name {vnet} --subnet {subnet} --auxiliary-mode MaxConnections --auxiliary-sku A1 --accelerated-networking true --tags fastpathenabled=true', checks=[
            self.check('NewNIC.auxiliaryMode', 'MaxConnections'),
            self.check('NewNIC.auxiliarySku', 'A1'),
            self.check('NewNIC.enableAcceleratedNetworking', True),
            self.check('NewNIC.tags.fastpathenabled', 'true')
        ])
        self.cmd('network nic update -g {rg} -n {nic} --auxiliary-mode AcceleratedConnections --auxiliary-sku A2', checks=[
            self.check('auxiliaryMode', 'AcceleratedConnections'),
            self.check('auxiliarySku', 'A2'),
            self.check('enableAcceleratedNetworking', True),
            self.check('tags.fastpathenabled', 'true')
        ])


class NetworkNicAppGatewayScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_nic_app_gateway', location='eastus')
    def test_network_nic_app_gateway(self, resource_group):
        from azure.core.exceptions import HttpResponseError
        import json

        self.kwargs.update({
            'nic': 'nic1',
            'ag': 'ag1',
            'vnet': 'vnet1',
            'subnet1': 'subnet1',
            'subnet2': 'subnet2',
            'ip': 'ip1',
            'lb': 'lb1',
            'bap': 'bap1',
            'pool1': 'appGatewayBackendPool',
            'pool2': 'bepool2',
            'config1': 'ipconfig1',
            'config2': 'ipconfig2'
        })

        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name {subnet1}')
        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} -n {subnet2} --address-prefix 10.0.1.0/24 --default-outbound false')
        self.cmd('network application-gateway create -g {rg} -n {ag} --vnet-name {vnet} --subnet {subnet1} --priority 1001 --no-wait')
        self.cmd('network application-gateway wait -g {rg} -n {ag} --exists --timeout 120')
        self.kwargs['ipaddres'] = json.dumps(
            {
                "ip_address": "10.20.0.69"
            }
        )
        self.cmd("network application-gateway address-pool update -g {rg} --gateway-name {ag} -n {pool1} --add backendAddresses \'{ipaddres}\'", checks=[
            self.check('length(backendAddresses)', 1)
        ])
        self.kwargs['ipaddres'] = json.dumps(
            {
                "ip_address": "10.20.0.70"
            }
        )
        self.cmd("network application-gateway address-pool update -g {rg} --gateway-name {ag} -n {pool1} --add backendAddresses \'{ipaddres}\'", checks=[
            self.check('length(backendAddresses)', 2)
        ])
        self.cmd('network application-gateway address-pool create -g {rg} --gateway-name {ag} -n {pool2} --no-wait')
        self.cmd('network lb create -g {rg} -n {lb}')
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n {bap}')
        self.cmd('network nic create -g {rg} -n {nic} --subnet {subnet2} --vnet-name {vnet} --gateway-name {ag} --app-gateway-address-pools {pool1}',
                 checks=self.check('length(NewNIC.ipConfigurations[0].applicationGatewayBackendAddressPools)', 1))
        with self.assertRaisesRegex(HttpResponseError, 'not supported for secondary IpConfigurations'):
            self.cmd('network nic ip-config create -g {rg} --nic-name {nic} -n {config2} --subnet {subnet2} --vnet-name {vnet} --gateway-name {ag} --app-gateway-address-pools {pool2}')
        self.cmd('network nic ip-config update -g {rg} --nic-name {nic} -n {config1} --gateway-name {ag} --app-gateway-address-pools {pool1} {pool2}',
                 checks=self.check('length(applicationGatewayBackendAddressPools)', 2))
        self.cmd('az network nic ip-config address-pool add -g {rg} --nic-name {nic} --lb-name {lb} --address-pool {bap} --ip-config-name {config1}')


class NetworkNicSubresourceScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_nic_subresource')
    def test_network_nic_subresources(self, resource_group):

        self.kwargs['nic'] = 'nic1'

        self.cmd('network vnet create -g {rg} -n vnet1 --subnet-name subnet1')
        self.cmd('network nic create -g {rg} -n {nic} --subnet subnet1 --vnet-name vnet1')
        self.cmd('network nic ip-config list -g {rg} --nic-name {nic}',
                 checks=self.check('length(@)', 1))
        self.cmd('network nic ip-config show -g {rg} --nic-name {nic} -n ipconfig1', checks=[
            self.check('name', 'ipconfig1'),
            self.check('privateIPAllocationMethod', 'Dynamic')
        ])
        self.cmd('network nic ip-config create -g {rg} --nic-name {nic} -n ipconfig2 --make-primary',
                 checks=self.check('primary', True))
        self.cmd('network nic ip-config update -g {rg} --nic-name {nic} -n ipconfig1 --make-primary',
                 checks=self.check('primary', True))
        self.cmd('network nic ip-config delete -g {rg} --nic-name {nic} -n ipconfig2')

        # test various sets
        self.kwargs.update({
            'vnet': 'vnet2',
            'subnet': 'subnet2',
            'ip': 'publicip2',
            'lb': 'lb1',
            'config': 'ipconfig1'
        })
        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name {subnet}')
        self.cmd('network public-ip create -g {rg} -n {ip}')
        self.kwargs['ip_id'] = self.cmd('network public-ip show -g {rg} -n {ip}').get_output_in_json()['id']
        self.cmd('network lb create -g {rg} -n {lb}')
        self.cmd('network lb inbound-nat-rule create -g {rg} --lb-name {lb} -n rule1 --protocol tcp --frontend-port 100 --backend-port 100 --frontend-ip-name LoadBalancerFrontEnd')
        self.cmd('network lb inbound-nat-rule create -g {rg} --lb-name {lb} -n rule2 --protocol tcp --frontend-port 200 --backend-port 200 --frontend-ip-name LoadBalancerFrontEnd')
        self.kwargs['rule1_id'] = self.cmd('network lb inbound-nat-rule show -g {rg} --lb-name {lb} -n rule1').get_output_in_json()['id']
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n bap1')
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n bap2')
        self.kwargs['bap1_id'] = self.cmd('network lb address-pool show -g {rg} --lb-name {lb} -n bap1').get_output_in_json()['id']

        self.kwargs['private_ip'] = '10.0.0.15'
        # test ability to set load balancer IDs
        # includes the default backend pool
        self.cmd('network nic ip-config update -g {rg} --nic-name {nic} -n {config} --lb-name {lb} --lb-address-pools {bap1_id} bap2 --lb-inbound-nat-rules {rule1_id} rule2 --private-ip-address {private_ip}', checks=[
            self.check('length(loadBalancerBackendAddressPools)', 2),
            self.check('length(loadBalancerInboundNatRules)', 2),
            self.check('privateIPAddress', '{private_ip}'),
            self.check('privateIPAllocationMethod', 'Static')])
        # test generic update
        self.cmd('network nic ip-config update -g {rg} --nic-name {nic} -n {config} --set privateIPAddress=10.0.0.50',
                 checks=self.check('privateIPAddress', '10.0.0.50'))

        # test ability to add and remove IDs one at a time with subcommands
        self.cmd('network nic ip-config inbound-nat-rule remove -g {rg} --lb-name {lb} --nic-name {nic} --ip-config-name {config} --inbound-nat-rule rule1')
        self.cmd('network nic ip-config inbound-nat-rule add -g {rg} --lb-name {lb} --nic-name {nic} --ip-config-name {config} --inbound-nat-rule rule1',
                 checks=self.check('length(loadBalancerInboundNatRules)', 2))

        self.cmd('network nic ip-config address-pool remove -g {rg} --lb-name {lb} --nic-name {nic} --ip-config-name {config} --address-pool bap1')
        self.cmd('network nic ip-config address-pool add -g {rg} --lb-name {lb} --nic-name {nic} --ip-config-name {config} --address-pool bap1',
                 checks=self.check('length(loadBalancerBackendAddressPools)', 2))

        self.cmd('network nic ip-config update -g {rg} --nic-name {nic} -n {config} --private-ip-address "" --public-ip-address {ip_id}', checks=[
            self.check('privateIPAllocationMethod', 'Dynamic'),
            self.check("publicIPAddress.contains(id, '{ip_id}')", True)
        ])

        self.cmd('network nic ip-config update -g {rg} --nic-name {nic} -n {config} --subnet {subnet} --vnet-name {vnet}',
                 checks=self.check("subnet.contains(id, '{subnet}')", True))

    @ResourceGroupPreparer(name_prefix="cli_test_multiple_ipconfigs_update_with_asg_", location="westus")
    def test_multiple_ipconfigs_update_with_asg(self):
        self.kwargs.update({
            "nic_name": self.create_random_name("nic-", 8),
            "vnet_name": self.create_random_name("vnet-", 12),
            "subnet_name": self.create_random_name("subnet-", 12),
            "asg_name": self.create_random_name("asg-", 8),
        })

        self.cmd("network vnet create -n {vnet_name} -g {rg} --subnet-name {subnet_name}")
        self.cmd("network nic create -n {nic_name} -g {rg} --vnet-name {vnet_name} --subnet {subnet_name}")
        self.cmd("network nic ip-config create -n ipconfig2 -g {rg} --nic-name {nic_name}")
        self.kwargs["asg_id"] = self.cmd("network asg create -n {asg_name} -g {rg}").get_output_in_json()["id"]

        self.cmd("network nic ip-config update -n ipconfig1 -g {rg} --nic-name {nic_name} --asgs {asg_name}")
        self.cmd(
            "network nic show -n {nic_name} -g {rg}",
            checks=[
                self.check("ipConfigurations | length(@)", 2),
                self.check("ipConfigurations[0].name", "ipconfig1"),
                self.check("ipConfigurations[1].name", "ipconfig2"),
                self.check("ipConfigurations[0].applicationSecurityGroups[0].id", "{asg_id}"),
                self.check("ipConfigurations[1].applicationSecurityGroups[0].id", "{asg_id}"),
            ]
        )

    @ResourceGroupPreparer(name_prefix="cli_test_multiple_ipconfigs_update_with_shorthand_", location="westus")
    def test_multiple_ipconfigs_remove_by_shorthand(self):
        self.kwargs.update({
            "nic": self.create_random_name("nic-", 8),
            "vnet": self.create_random_name("vnet-", 12),
            "subnet": self.create_random_name("subnet-", 12),
        })

        self.cmd("network vnet create -n {vnet} -g {rg} --subnet-name {subnet}")
        self.cmd("network nic create -n {nic} -g {rg} --vnet-name {vnet} --subnet {subnet}")

        # `ipconfg1` implicitly created
        self.cmd("network nic ip-config create -n ipconfig2 -g {rg} --nic-name {nic}")
        self.cmd("network nic ip-config create -n ipconfig3 -g {rg} --nic-name {nic}")
        self.cmd("network nic ip-config create -n ipconfig4 -g {rg} --nic-name {nic}")
        self.cmd("network nic ip-config create -n ipconfig5 -g {rg} --nic-name {nic}")

        self.cmd(
            "network nic update -n {nic} -g {rg} --ip-configurations [1]=null [2]=null [4]=null",
            checks=[
                self.check("ipConfigurations | length(@)", 2),
                self.check("ipConfigurations[0].name", "ipconfig1"),
                self.check("ipConfigurations[1].name", "ipconfig4"),
            ]
        )

    @ResourceGroupPreparer(name_prefix='cli_test_nic_lb_address_pools', location='eastus2')
    def test_network_nic_lb_address_pools(self, resource_group):

        self.kwargs.update({
            'nic': 'nic1',
            'vnet': 'vnet1',
            'subnet': 'subnet1',
            'config': 'ipconfig1',
            'lb': 'lb1',
            'pool': 'pool1'
        })

        self.cmd('network vnet create -g {rg} -n vnet1 --subnet-name subnet1')
        self.cmd('network nic create -g {rg} -n {nic} --subnet subnet1 --vnet-name vnet1')

        self.cmd('network lb create -g {rg} -n {lb}')
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n {pool}')
        self.kwargs['lb_pool_id'] = self.cmd('network lb address-pool show -g {rg} --lb-name {lb} -n {pool}').get_output_in_json()['id']

        self.cmd('network nic ip-config address-pool add -g {rg} --lb-name {lb} --nic-name {nic} --ip-config-name {config} --address-pool {pool}',
                 checks=self.check('length(loadBalancerBackendAddressPools)', 1))
        self.cmd('network nic ip-config address-pool remove -g {rg} --lb-name {lb} --nic-name {nic} --ip-config-name {config} --address-pool {pool}')
        self.cmd('network nic ip-config address-pool add -g {rg} --nic-name {nic} --ip-config-name {config} --address-pool {lb_pool_id}',
                 checks=self.check('length(loadBalancerBackendAddressPools)', 1))
        self.cmd('network nic ip-config address-pool remove -g {rg} --nic-name {nic} --ip-config-name {config} --address-pool {lb_pool_id}')

    @ResourceGroupPreparer(name_prefix='cli_test_nic_ag_address_pools')
    def test_network_nic_ag_address_pools(self, resource_group):

        self.kwargs.update({
            'nic': 'nic1',
            'vnet': 'vnet1',
            'subnet1': 'subnet1',
            'subnet2': 'subnet2',
            'config': 'ipconfig1',
            'ag': 'ag1',
            'pool': 'pool1'
        })

        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name {subnet1}')
        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} -n {subnet2} --address-prefix 10.0.1.0/24 --default-outbound false')
        self.cmd('network application-gateway create -g {rg} -n {ag} --vnet-name {vnet} --subnet {subnet1} --priority 1001 --no-wait')
        self.cmd('network application-gateway wait -g {rg} -n {ag} --exists --timeout 120')
        self.cmd('network application-gateway address-pool create -g {rg} --gateway-name {ag} -n {pool} --no-wait')
        self.kwargs['ag_pool_id'] = self.cmd('network application-gateway address-pool show -g {rg} --gateway-name {ag} -n {pool}').get_output_in_json()['id']

        self.cmd('network nic create -g {rg} -n {nic} --subnet {subnet2} --vnet-name {vnet}')

        self.cmd('network nic ip-config address-pool add -g {rg} --gateway-name {ag} --nic-name {nic} --ip-config-name {config} --address-pool {pool}',
                 checks=self.check('length(applicationGatewayBackendAddressPools)', 1))
        self.cmd('network nic ip-config address-pool remove -g {rg} --gateway-name {ag} --nic-name {nic} --ip-config-name {config} --address-pool {pool}')
        self.cmd('network nic ip-config address-pool add -g {rg} --nic-name {nic} --ip-config-name {config} --address-pool {ag_pool_id}',
                 checks=self.check('length(applicationGatewayBackendAddressPools)', 1))
        self.cmd('network nic ip-config address-pool remove -g {rg} --nic-name {nic} --ip-config-name {config} --address-pool {ag_pool_id}')

    @ResourceGroupPreparer(name_prefix='cli_test_nic_ip_config_private_ip_address_prefix_length')
    def test_network_nic_nic_ip_config_private_ip_address_prefix_length(self, resource_group):
        self.kwargs.update({
            'nic': self.create_random_name('nic', 10),
            'vnet': self.create_random_name('vnet', 10),
            'subnet': self.create_random_name('subnet', 10),
            'config1': self.create_random_name('config', 10),
            'config2': self.create_random_name('config', 10)
        })
        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name {subnet} --address-prefix 10.0.0.0/16 --subnet-prefix 10.0.0.0/24')
        self.cmd('network nic create -g {rg} -n {nic} --vnet-name {vnet} --subnet {subnet} --accelerated-networking true ')
        self.cmd('network nic ip-config create -g {rg} -n {config1} --nic-name {nic} --private-ip-address-version IPv4 --private-ip-address-prefix-length 28 --make-primary false', checks=[
            self.check('privateIPAddressPrefixLength', 28)
        ])

        self.cmd('network nic ip-config create -g {rg} -n {config2} --nic-name {nic}  --private-ip-address-version IPv4 ', checks=[
            self.check('privateIPAddressPrefixLength', None)
        ])
        self.cmd('network nic ip-config update -g {rg} -n {config2} --nic-name {nic} --private-ip-address-prefix-length 28', checks=[
            self.check('privateIPAddressPrefixLength', 28)
        ])


class NetworkNicConvenienceCommandsScenarioTest(ScenarioTest):

    @AllowLargeResponse(size_kb=99999)
    @ResourceGroupPreparer(name_prefix='cli_nic_convenience_test')
    def test_network_nic_convenience_commands(self, resource_group):
        self.kwargs.update({
            'vm': 'conveniencevm1',
            'subnet': 'subnet1',
            'vnet': 'vnet1'
        })

        self.cmd('vm create -g {rg} -n {vm} --image Canonical:UbuntuServer:18.04-LTS:latest --admin-username myusername --admin-password aBcD1234!@#$ --authentication-type password --subnet {subnet} --vnet-name {vnet} --nsg-rule None')

        # Disable default outbound access
        self.cmd('network vnet subnet update -g {rg} --vnet-name {vnet} -n {subnet} --default-outbound-access false')

        self.kwargs['nic_id'] = self.cmd('vm show -g {rg} -n {vm} --query "networkProfile.networkInterfaces[0].id"').get_output_in_json()
        self.cmd('network nic list-effective-nsg --ids {nic_id}',
                 checks=self.greater_than('length(@)', 0))
        self.cmd('network nic show-effective-route-table --ids {nic_id}',
                 checks=self.greater_than('length(@)', 0))
        self.cmd('network nic show-effective-route-table --ids {nic_id} -o table')


class NetworkExtendedNSGScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_extended_nsg')
    def test_network_extended_nsg(self, resource_group):

        self.kwargs.update({
            'nsg': 'nsg1',
            'rule': 'rule1'
        })
        self.cmd('network nsg create --name {nsg} -g {rg}')
        self.cmd('network nsg rule create --access allow --destination-address-prefixes 10.0.0.0/24 11.0.0.0/24 --direction inbound --nsg-name {nsg} -g {rg} --source-address-prefixes * -n {rule} --source-port-ranges 700-900 1000-1100 --priority 1000', checks=[
            self.check('length(destinationAddressPrefixes)', 2),
            self.check('destinationAddressPrefix', None),
            self.check('length(sourceAddressPrefixes)', 0),
            self.check('sourceAddressPrefix', '*'),
            self.check('length(sourcePortRanges)', 2),
            self.check('sourcePortRange', None),
            self.check('length(destinationPortRanges)', 0),
            self.check('destinationPortRange', '80')
        ])
        self.cmd('network nsg rule update --destination-address-prefixes Internet --nsg-name {nsg} -g {rg} --source-address-prefixes 10.0.0.0/24 11.0.0.0/24 -n {rule} --source-port-ranges * --destination-port-ranges 500-1000 2000 3000', checks=[
            self.check('length(destinationAddressPrefixes)', 0),
            self.check('destinationAddressPrefix', 'Internet'),
            self.check('length(sourceAddressPrefixes)', 2),
            self.check('sourceAddressPrefix', None),
            self.check('length(sourcePortRanges)', 0),
            self.check('sourcePortRange', '*'),
            self.check('length(destinationPortRanges)', 3),
            self.check('destinationPortRange', None)
        ])


class NetworkSecurityGroupScenarioTest(ScenarioTest):

    @AllowLargeResponse()
    @ResourceGroupPreparer(name_prefix='cli_test_nsg')
    def test_network_nsg(self, resource_group):

        self.kwargs.update({
            'nsg': 'test-nsg1',
            'rule': 'web',
            'rt': 'Microsoft.Network/networkSecurityGroups'
        })

        self.cmd('network nsg create --name {nsg} -g {rg} --tags foo=doo')
        self.cmd('network nsg rule create --access allow --destination-address-prefixes 1234 --direction inbound --nsg-name {nsg} --protocol * -g {rg} --source-address-prefixes 789 -n {rule} --source-port-ranges * --destination-port-ranges 4444 --priority 1000')

        self.cmd('network nsg list', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?type == '{rt}']) == length(@)", True)
        ])
        self.cmd('network nsg list --resource-group {rg}', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?type == '{rt}']) == length(@)", True),
            self.check("length([?resourceGroup == '{rg}']) == length(@)", True)
        ])
        self.cmd('network nsg show --resource-group {rg} --name {nsg}', checks=[
            self.check('type(@)', 'object'),
            self.check('type', '{rt}'),
            self.check('resourceGroup', '{rg}'),
            self.check('name', '{nsg}')
        ])
        # Test for the manually added nsg rule
        self.cmd('network nsg rule list --resource-group {rg} --nsg-name {nsg}', checks=[
            self.check('type(@)', 'array'),
            self.check('length(@)', 1),
            self.check("length([?resourceGroup == '{rg}']) == length(@)", True)
        ])
        self.cmd('network nsg rule list --resource-group {rg} --nsg-name {nsg} -o table')
        self.cmd('network nsg rule show --resource-group {rg} --nsg-name {nsg} --name {rule}', checks=[
            self.check('type(@)', 'object'),
            self.check('resourceGroup', '{rg}'),
            self.check('name', '{rule}')
        ])

        self.kwargs.update({
            'access': 'DENY',
            'prefix': '111',
            'dir': 'Outbound',
            'protocol': 'Tcp',
            'ports': '1234-1235',
            'desc': 'greatrule',
            'priority': 888
        })
        self.cmd('network nsg rule update -g {rg} --nsg-name {nsg} -n {rule} --direction {dir} --access {access} --destination-address-prefixes {prefix} --protocol {protocol} --source-address-prefixes {prefix} --source-port-ranges {ports} --destination-port-ranges {ports} --priority {priority} --description {desc}', checks=[
            self.check('access', 'Deny'),
            self.check('direction', '{dir}'),
            self.check('destinationAddressPrefix', '{prefix}'),
            self.check('protocol', '{protocol}'),
            self.check('sourceAddressPrefix', '{prefix}'),
            self.check('sourcePortRange', '{ports}'),
            self.check('priority', '{priority}'),
            self.check('description', '{desc}')
        ])

        # test generic update
        self.cmd('network nsg rule update -g {rg} --nsg-name {nsg} -n {rule} --set description="cool"',
                 checks=self.check('description', 'cool'))

        self.kwargs.update({
            'nsg2': 'test-nsg2',
            'asg': 'test-asg1',
            'asg2': 'test-asg2',
            'rule2': 'test-rule2',
            'prefix': '1234',
        })
        # test --destination-asgs in nsg rule
        self.cmd('network nsg create --name {nsg2} -g {rg}')
        self.cmd('network asg create --name {asg} -g {rg}')
        self.cmd('network asg create --name {asg2} -g {rg}')
        self.cmd('network nsg rule create -g {rg} --nsg-name {nsg2} -n {rule2} --priority 500 --source-address-prefixes Internet --destination-port-ranges 80 8080 --destination-asgs {asg} --access Allow --protocol Tcp',
                 checks=[self.check('name', '{rule2}'),
                         self.check('ends_with(@.destinationApplicationSecurityGroups[0].id, `/{asg}`)', True)])
        self.cmd('network nsg rule update -g {rg} --nsg-name {nsg2} -n {rule2} --destination-asgs {asg2}',
                 checks=[self.check('name', '{rule2}'),
                         self.check('ends_with(@.destinationApplicationSecurityGroups[0].id, `/{asg2}`)', True)])
        self.cmd('network nsg rule update -g {rg} --nsg-name {nsg2} -n {rule2} --destination-asgs "" --destination-address-prefix {prefix}',
                 checks=[self.check('name', '{rule2}'),
                         self.check('destinationApplicationSecurityGroups', None)])

        self.cmd('network nsg rule delete --resource-group {rg} --nsg-name {nsg} --name {rule}')
        self.cmd('network nsg rule delete --resource-group {rg} --nsg-name {nsg2} --name {rule2}')
        # Delete the network security group
        self.cmd('network nsg delete --resource-group {rg} --name {nsg}')
        self.cmd('network nsg delete --resource-group {rg} --name {nsg2}')
        # Expecting no results as we just deleted the only security group in the resource group
        self.cmd('network nsg list --resource-group {rg}', checks=self.is_empty())


class NetworkRouteTableOperationScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_route_table')
    def test_network_route_table_operation(self, resource_group):

        self.kwargs.update({
            'table': 'cli-test-route-table',
            'route': 'my-route',
            'rt': 'Microsoft.Network/routeTables'
        })

        self.cmd('network route-table create -n {table} -g {rg} --tags foo=doo',
                 checks=self.check('tags.foo', 'doo'))
        self.cmd('network route-table update -n {table} -g {rg} --tags foo=boo --disable-bgp-route-propagation', checks=[
            self.check('tags.foo', 'boo')
        ])
        self.cmd('network route-table route create --address-prefix 10.0.5.0/24 -n {route} -g {rg} --next-hop-type None --route-table-name {table}')

        self.cmd('network route-table list -g {rg}',
                 checks=self.check('type(@)', 'array'))
        self.cmd('network route-table list --resource-group {rg}', checks=[
            self.check('type(@)', 'array'),
            self.check('length(@)', 1),
            self.check('[0].name', '{table}'),
            self.check('[0].type', '{rt}')
        ])
        self.cmd('network route-table show --resource-group {rg} --name {table}', checks=[
            self.check('type(@)', 'object'),
            self.check('name', '{table}'),
            self.check('type', '{rt}')
        ])
        self.cmd('network route-table route list --resource-group {rg} --route-table-name {table}',
                 checks=self.check('type(@)', 'array'))
        self.cmd('network route-table route show --resource-group {rg} --route-table-name {table} --name {route}', checks=[
            self.check('type(@)', 'object'),
            self.check('name', '{route}'),
        ])
        # test route-table route update
        self.cmd('network route-table route update -g {rg} -n {route} --route-table-name {table} --next-hop-type VirtualNetworkGateway' , checks=[
            self.check('nextHopType', 'VirtualNetworkGateway')
            ])

        self.cmd('network route-table route delete --resource-group {rg} --route-table-name {table} --name {route}')
        self.cmd('network route-table route list --resource-group {rg} --route-table-name {table}', checks=self.is_empty())
        self.cmd('network route-table delete --resource-group {rg} --name {table}')
        self.cmd('network route-table list --resource-group {rg}', checks=self.is_empty())

    @ResourceGroupPreparer(name_prefix='cli_test_route_table_disable_peering')
    def test_network_route_table_disable_peering_route(self, resource_group):
        self.kwargs.update({
            'table': 'cli-test-rt-peering',
        })

        # create route table without --disable-peering-route (default None)
        self.cmd('network route-table create -n {table} -g {rg}', checks=[
            self.check('disablePeeringRoute', None)
        ])

        self.cmd('network route-table show -g {rg} -n {table}', checks=[
            self.check('disablePeeringRoute', None)
        ])

        # update with --disable-peering-route All
        self.cmd('network route-table update -n {table} -g {rg} --disable-peering-route All', checks=[
            self.check('disablePeeringRoute', 'All')
        ])

        self.cmd('network route-table show -g {rg} -n {table}', checks=[
            self.check('disablePeeringRoute', 'All')
        ])

        self.cmd('network route-table list -g {rg}', checks=[
            self.check('[0].disablePeeringRoute', 'All')
        ])

        # create a new route table with --disable-peering-route All directly
        self.kwargs['table2'] = 'cli-test-rt-peering2'
        self.cmd('network route-table create -n {table2} -g {rg} --disable-peering-route All', checks=[
            self.check('disablePeeringRoute', 'All')
        ])

        # update to reset --disable-peering-route to None
        self.cmd('network route-table update -n {table2} -g {rg} --disable-peering-route None', checks=[
            self.check('disablePeeringRoute', None)
        ])

        self.cmd('network route-table delete -g {rg} -n {table}')
        self.cmd('network route-table delete -g {rg} -n {table2}')


class NetworkVNetScenarioTest(ScenarioTest):

    @AllowLargeResponse()
    @ResourceGroupPreparer(name_prefix='cli_vnet_test')
    def test_network_vnet(self, resource_group):

        self.kwargs.update({
            'vnet': 'vnet1',
            'subnet': 'subnet1',
            'rt': 'Microsoft.Network/virtualNetworks'
        })

        self.cmd('network vnet create --resource-group {rg} --name {vnet} --subnet-name default', checks=[
            self.check('newVNet.provisioningState', 'Succeeded'),
            self.check('newVNet.addressSpace.addressPrefixes[0]', '10.0.0.0/16'),
            self.check('newVNet.subnets[0].privateEndpointNetworkPolicies', 'Disabled')
        ])
        self.cmd('network vnet check-ip-address -g {rg} -n {vnet} --ip-address 10.0.0.50',
                 checks=self.check('available', True))

        self.cmd('network vnet check-ip-address -g {rg} -n {vnet} --ip-address 10.0.0.0',
                 checks=self.check('available', False))

        self.cmd('network vnet list', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?type == '{rt}']) == length(@)", True)
        ])
        self.cmd('network vnet list --resource-group {rg}', checks=[
            self.check('type(@)', 'array'),
            self.check("length([?type == '{rt}']) == length(@)", True),
        ])
        self.cmd("network vnet list -o table")
        self.cmd('network vnet show --resource-group {rg} --name {vnet}', checks=[
            self.check('type(@)', 'object'),
            self.check('name', '{vnet}'),
            self.check('type', '{rt}')
        ])
        self.kwargs['prefixes'] = '20.0.0.0/16 10.0.0.0/16'
        self.cmd('network vnet update --resource-group {rg} --name {vnet} --address-prefixes {prefixes} --dns-servers 1.2.3.4', checks=[
            self.check('length(addressSpace.addressPrefixes)', 2),
            self.check('dhcpOptions.dnsServers[0]', '1.2.3.4')
        ])
        self.cmd('network vnet update -g {rg} -n {vnet} --dns-servers null', checks=[
            self.check('length(addressSpace.addressPrefixes)', 2),
            self.check('dhcpOptions.dnsServers', [])
        ])

        # test generic update
        self.cmd('network vnet update --resource-group {rg} --name {vnet} --set addressSpace.addressPrefixes[0]="20.0.0.0/24"',
                 checks=self.check('addressSpace.addressPrefixes[0]', '20.0.0.0/24'))

        self.cmd('network vnet subnet create --resource-group {rg} --vnet-name {vnet} --name {subnet} --address-prefix 20.0.0.0/24 --default-outbound false')
        self.cmd('network vnet subnet list --resource-group {rg} --vnet-name {vnet}',
                 checks=self.check('type(@)', 'array'))
        self.cmd('network vnet subnet show --resource-group {rg} --vnet-name {vnet} --name {subnet}', checks=[
            self.check('type(@)', 'object'),
            self.check('name', '{subnet}'),
        ])

        self.cmd('network vnet subnet delete --resource-group {rg} --vnet-name {vnet} --name {subnet}')
        self.cmd('network vnet subnet list --resource-group {rg} --vnet-name {vnet}',
                 checks=self.check("length([?name == '{subnet}'])", 0))

        self.cmd('network vnet list --resource-group {rg}',
                 checks=self.check("length([?name == '{vnet}'])", 1))
        self.cmd('network vnet delete --resource-group {rg} --name {vnet}')
        self.cmd('network vnet list --resource-group {rg}', checks=self.is_empty())

    @live_only()
    @ResourceGroupPreparer(name_prefix='cli_vnet_with_ipam_pool_test', location='westus')
    @AllowLargeResponse(size_kb=99999)
    def test_network_vnet_subnet_with_ipam_pool(self, resource_group, resource_group_location):

        self.kwargs.update({
            'rg': resource_group,
            'location': resource_group_location,
            'manager': 'manager1',
            'pool': 'pool1',
            'vnet': 'vnet1',
            'subnet': 'subnet1'
        })
        self.cmd('extension add -n virtual-network-manager')
        self.kwargs['sub_id'] = self.get_subscription_id()
        self.cmd('network manager create -g {rg} -n {manager} -l {location} --scope-accesses "SecurityAdmin" "Connectivity" --network-manager-scopes subscriptions="/subscriptions/{sub_id}"')
        self.kwargs['pool_id'] = self.cmd('network manager ipam-pool create --manager-name {manager} -g {rg} --name {pool} --address-prefix 10.1.0.0/16').get_output_in_json()['id']

        self.cmd('network vnet create -g {rg} -n {vnet} --ipam-allocations [0].id={pool_id} [0].number-of-ip-addresses=10', checks=[
            self.check('newVNet.addressSpace.ipamPoolPrefixAllocations[0].id', '{pool_id}'),
            self.check('newVNet.addressSpace.ipamPoolPrefixAllocations[0].numberOfIpAddresses', 10),
            self.check('newVNet.addressSpace.ipamPoolPrefixAllocations[0].resourceGroup', '{rg}')
        ])

        self.cmd('network vnet subnet create -g {rg} -n {subnet} --vnet-name {vnet} --ipam-allocations [0].id={pool_id} [0].number-of-ip-addresses=5', checks=[
            self.check('ipamPoolPrefixAllocations[0].id', '{pool_id}'),
            self.check('ipamPoolPrefixAllocations[0].numberOfIpAddresses', 5),
            self.check('ipamPoolPrefixAllocations[0].resourceGroup', '{rg}')
        ])

    @live_only()
    @ResourceGroupPreparer(name_prefix='cli_vnet_summarized_gw_ipam', location='centraluseuap')
    @AllowLargeResponse(size_kb=99999)
    def test_network_vnet_with_summarized_gateway_prefixes_ipam(self, resource_group, resource_group_location):

        self.kwargs.update({
            'rg': resource_group,
            'location': resource_group_location,
            'manager': 'manager1',
            'pool': 'pool1',
            'vnet': 'vnet1',
        })
        self.cmd('extension add -n virtual-network-manager')
        self.kwargs['sub_id'] = self.get_subscription_id()
        self.cmd('network manager create -g {rg} -n {manager} -l {location} --scope-accesses "SecurityAdmin" "Connectivity" --network-manager-scopes subscriptions="/subscriptions/{sub_id}"')
        self.kwargs['pool_id'] = self.cmd('network manager ipam-pool create --manager-name {manager} -g {rg} --name {pool} --address-prefix 10.1.0.0/16').get_output_in_json()['id']

        self.cmd(
            'network vnet create -g {rg} -n {vnet} --address-prefixes 10.0.0.0/16 '
            '--summarized-gateway-prefixes ipam-pool-prefix-allocations="[{{id:{pool_id},number-of-ip-addresses:10}}]"',
            checks=[
                self.check('newVNet.provisioningState', 'Succeeded'),
                self.check('newVNet.summarizedGatewayPrefixes.ipamPoolPrefixAllocations[0].id', '{pool_id}'),
                self.check('newVNet.summarizedGatewayPrefixes.ipamPoolPrefixAllocations[0].numberOfIpAddresses', 10),
            ]
        )

        self.cmd('network vnet show -g {rg} -n {vnet}', checks=[
            self.check('summarizedGatewayPrefixes.ipamPoolPrefixAllocations[0].id', '{pool_id}'),
            self.check('summarizedGatewayPrefixes.ipamPoolPrefixAllocations[0].numberOfIpAddresses', 10),
        ])

        self.cmd(
            'network vnet update -g {rg} -n {vnet} --summarized-gateway-prefixes null',
            checks=[
                self.check('summarizedGatewayPrefixes', None),
            ]
        )

    @ResourceGroupPreparer(name_prefix='cli_vnet_with_summarized_gw_prefixes', location='centraluseuap')
    def test_network_vnet_with_summarized_gateway_prefixes(self, resource_group):

        self.kwargs.update({
            'vnet': 'vnet1',
        })

        self.cmd(
            'network vnet create -g {rg} -n {vnet} --address-prefixes 10.0.0.0/16 '
            '--summarized-gateway-prefixes address-prefixes="[10.0.0.0/16]"',
            checks=[
                self.check('newVNet.provisioningState', 'Succeeded'),
                self.check('newVNet.summarizedGatewayPrefixes.addressPrefixes[0]', '10.0.0.0/16'),
            ]
        )

        self.cmd('network vnet show -g {rg} -n {vnet}', checks=[
            self.check('summarizedGatewayPrefixes.addressPrefixes[0]', '10.0.0.0/16'),
        ])

        self.cmd(
            'network vnet update -g {rg} -n {vnet} '
            '--summarized-gateway-prefixes address-prefixes="[10.0.0.0/16,10.1.0.0/16]"',
            checks=[
                self.check('summarizedGatewayPrefixes.addressPrefixes[0]', '10.0.0.0/16'),
                self.check('summarizedGatewayPrefixes.addressPrefixes[1]', '10.1.0.0/16'),
                self.check('length(summarizedGatewayPrefixes.addressPrefixes)', 2),
            ]
        )

        self.cmd(
            'network vnet update -g {rg} -n {vnet} --summarized-gateway-prefixes null',
            checks=[
                self.check('summarizedGatewayPrefixes', None),
            ]
        )

    @ResourceGroupPreparer(name_prefix='cli_vnet_with_subnet_nsg_test')
    def test_network_vnet_with_subnet_nsg(self, resource_group):

        self.kwargs.update({
            'vnet': 'vnet1',
            'subnet': 'subnet1',
            'nsg': 'nsg',
            'rt': 'Microsoft.Network/virtualNetworks',
            'prefixes': '20.0.0.0/16 10.0.0.0/16'
        })
        result = self.cmd('network nsg create --resource-group {rg} --name {nsg}').get_output_in_json()
        self.kwargs['nsg_id'] = result['NewNSG']['id']
        self.cmd('network vnet create --resource-group {rg} --name {vnet} --address-prefixes {prefixes} '
                 '--subnet-name {subnet} --subnet-prefixes 20.0.0.0/24 --nsg {nsg}')
        self.cmd('network vnet subnet list --resource-group {rg} --vnet-name {vnet}',
                 checks=self.check('type(@)', 'array'))
        self.cmd('network vnet subnet show --resource-group {rg} --vnet-name {vnet} --name {subnet}', checks=[
            self.check('type(@)', 'object'),
            self.check('name', '{subnet}'),
            self.check('networkSecurityGroup.id', '{nsg_id}')
        ])

        self.cmd('network vnet subnet delete --resource-group {rg} --vnet-name {vnet} --name {subnet}')

    @ResourceGroupPreparer(name_prefix='cli_vnet_test')
    def test_network_vnet_list_available_ips(self, resource_group):
        self.kwargs.update({
            'vnet': 'vnet1',
            'subnet': 'subnet1',
            'rt': 'Microsoft.Network/virtualNetworks',
            'rg': resource_group
        })

        self.cmd('network vnet create --resource-group {rg} --name {vnet} --subnet-name default', checks=[
            self.check('newVNet.provisioningState', 'Succeeded'),
            self.check('newVNet.addressSpace.addressPrefixes[0]', '10.0.0.0/16')
        ])
        self.kwargs['prefixes'] = '20.0.0.0/16 10.0.0.0/16'
        self.cmd('network vnet update --resource-group {rg} --name {vnet} --address-prefixes {prefixes} --dns-servers 1.2.3.4', checks=[
            self.check('length(addressSpace.addressPrefixes)', 2),
            self.check('dhcpOptions.dnsServers[0]', '1.2.3.4')
        ])

        self.cmd('network vnet subnet create --resource-group {rg} --vnet-name {vnet} --name {subnet} --address-prefix 20.0.0.0/24 --default-outbound false')

        self.cmd('network vnet list-available-ips -g {rg} --name {vnet}', checks=[
            self.check('length(@)', 5)
        ])

    @ResourceGroupPreparer(name_prefix='cli_vnet_with_bgp_community')
    def test_network_vnet_with_bgp_community(self, resource_group):
        self.kwargs.update({
            'vnet': 'vnet1',
            'subnet': 'subnet1',
        })

        self.cmd('network vnet create --resource-group {rg} --name {vnet} --subnet-name default --bgp-community "12076:20000"', checks=[
            self.check('newVNet.bgpCommunities.regionalCommunity', '12076:50006'),
            self.check('newVNet.bgpCommunities.virtualNetworkCommunity', '12076:20000')
        ])

        self.cmd('network vnet update --resource-group {rg} --name {vnet} --bgp-community "12076:20001"', checks=[
            self.check('bgpCommunities.regionalCommunity', '12076:50006'),
            self.check('bgpCommunities.virtualNetworkCommunity', '12076:20001')
        ])

    @ResourceGroupPreparer(name_prefix='cli_vnet_with_encryption')
    def test_network_vnet_with_encryption(self, resource_group):
        self.kwargs.update({
            'allowUnencrypted': 'AllowUnencrypted',
            'dropUnencrypted': 'DropUnencrypted',
        })
        # only create with --enable-encryption and --encryption-enforcement-policy
        self.cmd('network vnet create --address-prefixes 10.0.0.0/16 -n MyVnet1 -g {rg} --subnet-name Mysubnet --subnet-prefixes 10.0.0.0/24 --enable-encryption true --encryption-enforcement-policy allowUnencrypted')
        self.cmd('network vnet create --address-prefixes 10.1.0.0/16 -n MyVnet2 -g {rg} --subnet-name MySubnet --subnet-prefixes 10.1.0.0/24 --enable-encryption true --encryption-enforcement-policy dropUnencrypted')
        self.cmd('network vnet show -n MyVnet1 -g {rg}', checks=[
            self.check('encryption.enabled', True),
            self.check('encryption.enforcement', '{allowUnencrypted}'),
        ])
        self.cmd('network vnet show -n MyVnet2 -g {rg}', checks=[
            self.check('encryption.enabled', True),
            self.check('encryption.enforcement', '{dropUnencrypted}'),
        ])
        # only create with --enable-encryption
        self.cmd('network vnet create --address-prefixes 10.2.0.0/16 --name MyVnet3 --resource-group {rg} --subnet-name Mysubnet --subnet-prefixes 10.2.0.0/24 --enable-encryption false')
        self.cmd('network vnet create --address-prefixes 10.3.0.0/16 --name MyVnet4 --resource-group {rg} --subnet-name MySubnet --subnet-prefixes 10.3.0.0/24 --enable-encryption true', expect_failure=True)
        self.cmd('network vnet update --name MyVnet3 --resource-group {rg} --enable-encryption true --encryption-enforcement-policy allowUnencrypted', checks=[
            self.check('encryption.enabled', True),
            self.check('encryption.enforcement', '{allowUnencrypted}'),
        ])
        self.cmd('network vnet update --name MyVnet3 --resource-group {rg} --enable-encryption true --encryption-enforcement-policy dropUnencrypted', checks=[
            self.check('encryption.enabled', True),
            self.check('encryption.enforcement', '{dropUnencrypted}'),
        ])
        # create without encryption
        self.cmd('network vnet create --address-prefixes 10.5.0.0/16 --name MyVnet6 --resource-group {rg} --subnet-name Mysubnet --subnet-prefixes 10.5.0.0/24')
        self.cmd('network vnet create --address-prefixes 10.6.0.0/16 --name MyVnet7 --resource-group {rg} --subnet-name Mysubnet --subnet-prefixes 10.6.0.0/24')
        self.cmd('network vnet create --address-prefixes 10.7.0.0/16 --name MyVnet8 --resource-group {rg} --subnet-name Mysubnet --subnet-prefixes 10.7.0.0/24')
        # update
        self.cmd('network vnet update --name MyVnet6 --resource-group {rg} --enable-encryption true', expect_failure=True)
        self.cmd('network vnet update --name MyVnet7 --resource-group {rg} --encryption-enforcement-policy dropUnencrypted', expect_failure=True)
        self.cmd('network vnet update --name MyVnet8 --resource-group {rg} --enable-encryption true --encryption-enforcement-policy dropUnencrypted', checks=[
            self.check('encryption.enabled', True),
            self.check('encryption.enforcement', '{dropUnencrypted}'),
        ])
        # vnet peering
        self.cmd('network vnet peering create --name MyVnet1ToMyVnet2 --remote-vnet MyVnet2 --resource-group {rg} --vnet-name MyVnet1')
        self.cmd('network vnet peering show --name MyVnet1ToMyVnet2 --vnet-name MyVnet1 -g {rg}', checks=[
            self.check('remoteVirtualNetworkEncryption.enabled', True),
            self.check('remoteVirtualNetworkEncryption.enforcement', '{dropUnencrypted}'),
        ])

    @ResourceGroupPreparer(name_prefix='cli_vnet_subnet_test')
    def test_network_vnet_subnet_list_available_ips(self, resource_group):
        self.kwargs.update({
            'vnet': 'vnet1',
            'subnet': 'subnet1',
            'rt': 'Microsoft.Network/virtualNetworks',
            'rg': resource_group
        })

        self.cmd('network vnet create --resource-group {rg} --name {vnet} --subnet-name default', checks=[
            self.check('newVNet.provisioningState', 'Succeeded'),
            self.check('newVNet.addressSpace.addressPrefixes[0]', '10.0.0.0/16')
        ])

        self.cmd(
            'network vnet subnet create --resource-group {rg} --vnet-name {vnet} --name {subnet} --address-prefix 10.0.1.0/24 --default-outbound false')

        self.cmd('network vnet subnet list-available-ips -g {rg} --vnet-name {vnet} --name {subnet}', checks=[
            self.check('length(@)', 5)
        ])

class NetworkVNetCachingScenarioTest(ScenarioTest):
    @live_only()
    @ResourceGroupPreparer(name_prefix='cli_test_vnet_ids_query')
    def test_network_vnet_ids_query(self, resource_group):
        import json

        # This test ensures that --query works with --ids
        self.kwargs.update({
            'vnet1': 'vnet1',
            'vnet2': 'vnet2'
        })
        self.kwargs['id1'] = self.cmd('network vnet create -g {rg} -n {vnet1}').get_output_in_json()['newVNet']['id']
        self.kwargs['id2'] = self.cmd('network vnet create -g {rg} -n {vnet2}').get_output_in_json()['newVNet']['id']
        self.cmd('network vnet show --ids {id1} {id2} --query "[].name"', checks=[
            self.check('length(@)', 2),
            self.check("contains(@, '{vnet1}')", True),
            self.check("contains(@, '{vnet2}')", True),
        ])

        # This test ensures you can pipe a list of IDs to --ids
        self.kwargs['ids'] = self.cmd('network vnet list -g {rg} --query "[].id" -otsv').output
        self.cmd('network vnet show --ids {ids}',
                 checks=self.check('length(@)', 2))

        # This test ensures you can pipe JSON output to --ids Windows-style
        # ensures a single JSON string has its ids parsed out
        self.kwargs['json'] = json.dumps(self.cmd('network vnet list -g {rg}').get_output_in_json())
        self.cmd('network vnet show --ids \'{json}\'',
                 checks=self.check('length(@)', 2))

        # This test ensures you can pipe JSON output to --ids bash-style
        # ensures that a JSON string where each line is interpretted individually
        # is reassembled and treated as a single json string
        json_obj = self.cmd('network vnet list -g {rg}').get_output_in_json()
        for item in json_obj:
            del item['etag']
        split_json = json.dumps(json_obj, indent=4).split()
        split_string = ' '.join(split_json).replace('{', '{{').replace('}', '}}').replace('"', '\\"')
        self.cmd('network vnet show --ids {}'.format(split_string),
                 checks=self.check('length(@)', 2))


class NetworkVNetPeeringScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='test_network_vnet_flowtimeout', location='centraluseuap')
    def test_network_vnet_flowtimeout(self, resource_group):
        self.kwargs.update({
            'rg': resource_group,
            'time': 10,
            'time1': 20,
        })

        self.cmd('network vnet create -g {rg} -n vnet --flowtimeout {time}',
                 checks=self.check('newVNet.flowTimeoutInMinutes', '{time}'))
        self.cmd('network vnet update -g {rg} -n vnet --flowtimeout {time1}',
                 checks=self.check('flowTimeoutInMinutes', '{time1}'))

    @ResourceGroupPreparer(name_prefix='cli_test_vnet_peering')
    def test_network_vnet_peering(self, resource_group):

        # create two vnets with non-overlapping prefixes
        self.cmd('network vnet create -g {rg} -n vnet1')
        self.cmd('network vnet create -g {rg} -n vnet2 --subnet-name GatewaySubnet --address-prefix 11.0.0.0/16 --subnet-prefix 11.0.0.0/24')
        # create supporting resources for gateway
        self.cmd('network public-ip create -g {rg} -n ip1')
        ip_id = self.cmd('network public-ip show -g {rg} -n ip1 --query id').get_output_in_json()
        vnet_id = self.cmd('network vnet show -g {rg} -n vnet2 --query id').get_output_in_json()

        self.kwargs.update({
            'ip_id': ip_id,
            'vnet_id': vnet_id
        })
        # create the gateway on vnet2
        self.cmd('network vnet-gateway create -g {rg} -n gateway1 --public-ip-address {ip_id} --vnet {vnet_id} --tags foo=doo --sku VpnGw1')

        vnet1_id = self.cmd('network vnet show -g {rg} -n vnet1 --query id').get_output_in_json()
        vnet2_id = self.cmd('network vnet show -g {rg} -n vnet2 --query id').get_output_in_json()

        self.kwargs.update({
            'vnet1_id': vnet1_id,
            'vnet2_id': vnet2_id
        })
        # set up gateway sharing from vnet1 to vnet2. test that remote-vnet indeed accepts name or id.
        self.cmd('network vnet peering create -g {rg} -n peering2 --vnet-name vnet2 --remote-vnet {vnet1_id} --allow-gateway-transit', checks=[
            self.check('allowGatewayTransit', True),
            self.check('remoteVirtualNetwork.id', '{vnet1_id}'),
            self.check('peeringState', 'Initiated')
        ])
        self.cmd('network vnet peering create -g {rg} -n peering1 --vnet-name vnet1 --remote-vnet vnet2 --use-remote-gateways --allow-forwarded-traffic', checks=[
            self.check('useRemoteGateways', True),
            self.check('remoteVirtualNetwork.id', '{vnet2_id}'),
            self.check('peeringState', 'Connected'),
            self.check('allowVirtualNetworkAccess', False)
        ])
        self.cmd('network vnet peering show -g {rg} -n peering1 --vnet-name vnet1',
                 checks=self.check('name', 'peering1'))
        self.cmd('network vnet peering list -g {rg} --vnet-name vnet2', checks=[
            self.check('[0].name', 'peering2'),
            self.check('length(@)', 1)
        ])
        self.cmd('network vnet peering update -g {rg} -n peering1 --vnet-name vnet1 --set useRemoteGateways=false', checks=[
            self.check('useRemoteGateways', False),
            self.check('allowForwardedTraffic', True)
        ])
        self.cmd('network vnet peering delete -g {rg} -n peering1 --vnet-name vnet1')
        self.cmd('network vnet peering list -g {rg} --vnet-name vnet1',
                 checks=self.is_empty())
        # must delete the second peering and the gateway or the resource group delete will fail
        self.cmd('network vnet peering delete -g {rg} -n peering2 --vnet-name vnet2')
        self.cmd('network vnet-gateway delete -g {rg} -n gateway1')

    @ResourceGroupPreparer(name_prefix='cli_test_vnet_peering')
    def test_network_vnet_peering_sync(self, resource_group):

        # create two vnets with non-overlapping prefixes
        self.cmd('network vnet create -g {rg} -n vnet1')
        self.cmd('network vnet create -g {rg} -n vnet2 --subnet-name GatewaySubnet --address-prefix 11.0.0.0/16 --subnet-prefix 11.0.0.0/24')
        # create supporting resources for gateway
        self.cmd('network public-ip create -g {rg} -n ip1')
        ip_id = self.cmd('network public-ip show -g {rg} -n ip1 --query id').get_output_in_json()
        vnet_id = self.cmd('network vnet show -g {rg} -n vnet2 --query id').get_output_in_json()

        self.kwargs.update({
            'ip_id': ip_id,
            'vnet_id': vnet_id
        })
        # create the gateway on vnet2
        self.cmd('network vnet-gateway create -g {rg} -n gateway1 --public-ip-address {ip_id} --vnet {vnet_id} --tags foo=doo --sku VpnGw1')

        vnet1_id = self.cmd('network vnet show -g {rg} -n vnet1 --query id').get_output_in_json()
        vnet2_id = self.cmd('network vnet show -g {rg} -n vnet2 --query id').get_output_in_json()

        self.kwargs.update({
            'vnet1_id': vnet1_id,
            'vnet2_id': vnet2_id
        })
        # set up gateway sharing from vnet1 to vnet2. test that remote-vnet indeed accepts name or id.
        self.cmd('network vnet peering create -g {rg} -n peering2 --vnet-name vnet2 --remote-vnet {vnet1_id} --allow-gateway-transit', checks=[
            self.check('allowGatewayTransit', True),
            self.check('remoteVirtualNetwork.id', '{vnet1_id}'),
            self.check('peeringState', 'Initiated')
        ])
        self.cmd('network vnet peering create -g {rg} -n peering1 --vnet-name vnet1 --remote-vnet vnet2 --use-remote-gateways --allow-forwarded-traffic', checks=[
            self.check('useRemoteGateways', True),
            self.check('remoteVirtualNetwork.id', '{vnet2_id}'),
            self.check('peeringState', 'Connected'),
            self.check('allowVirtualNetworkAccess', False)
        ])

        self.cmd('network vnet peering sync -g {rg} -n peering1 --vnet-name vnet1')

    @ResourceGroupPreparer(name_prefix='cli_test_vnet_peering_with_params')
    def test_network_vnet_peering_with_params(self, resource_group):

        # create two vnets with non-overlapping prefixes
        self.cmd('network vnet create -g {rg} -n vnet1 --subnet-name Subnet1 --address-prefixes 10.0.0.0/27 10.0.1.0/27 --subnet-prefixes 10.0.0.0/27')
        self.cmd('network vnet create -g {rg} -n vnet2 --subnet-name Subnet2 --address-prefixes 20.0.0.0/27 --subnet-prefixes 20.0.0.0/27')

        vnet1_id = self.cmd('network vnet show -g {rg} -n vnet1 --query id').get_output_in_json()
        vnet2_id = self.cmd('network vnet show -g {rg} -n vnet2 --query id').get_output_in_json()

        self.kwargs.update({
            'vnet1_id': vnet1_id,
            'vnet2_id': vnet2_id
        })
        self.cmd('network vnet peering create -g {rg} -n peering2 --vnet-name vnet2 --remote-vnet {vnet1_id} --peer-complete-vnets false --local-subnet-names Subnet2 --remote-subnet-names Subnet1 --allow-vnet-access --allow-forwarded-traffic --allow-gateway-transit false --use-remote-gateways false --enable-only-ipv6 false', checks=[
            self.check('allowForwardedTraffic', True),
            self.check('allowGatewayTransit', False),
            self.check('allowVirtualNetworkAccess', True),
            self.check('useRemoteGateways', False),
            self.check('peerCompleteVnets', False),
            self.check('enableOnlyIPv6Peering', False),
            self.check('remoteVirtualNetwork.id', '{vnet1_id}'),
            self.check('remoteSubnetNames[0]', 'Subnet1'),
            self.check('localSubnetNames[0]', 'Subnet2'),
        ])
        self.cmd(
            "network vnet peering update -n peering2 -g {rg} --vnet-name vnet2 --remote-vnet {vnet1_id} "
            "--allow-vnet-access false --allow-forwarded-traffic false --allow-gateway-transit true",
            checks=[
                self.check("allowForwardedTraffic", False),
                self.check("allowGatewayTransit", True),
                self.check("allowVirtualNetworkAccess", False),
            ]
        )


class NetworkVpnConnectionIpSecPolicy(ScenarioTest):
    @live_only()
    @ResourceGroupPreparer(name_prefix='test_vpn_connection_aux_', location='westus')
    @ResourceGroupPreparer(name_prefix='test_vpn_connection_aux_', location='westus',
                           parameter_name='aux_resource_group', subscription=AUX_SUBSCRIPTION)
    def test_vpn_connection_aux(self, resource_group, aux_resource_group, resource_group_location,):
        self.kwargs.update({
            'rg': resource_group,
            'rg2': aux_resource_group,
            'location': resource_group_location,
            'aux_sub': AUX_SUBSCRIPTION,
            'vnet1': 'vnet1',
            'vnet_prefix1': '10.11.0.0/16',
            'vnet_prefix2': '10.12.0.0/16',
            'fe_sub1': 'FrontEnd',
            'fe_sub_prefix1': '10.11.0.0/24',
            'be_sub1': 'BackEnd',
            'be_sub_prefix1': '10.12.0.0/24',
            'gw_sub1': 'GatewaySubnet',
            'gw_sub_prefix1': '10.12.255.0/27',
            'gw1ip': 'pip1',
            'gw1': 'gw1',
            'gw1_sku': 'VpnGw1',
            'lgw1': 'lgw1',
            'lgw1ip': '131.107.72.22',
            'lgw1_prefix1': '10.61.0.0/16',
            'lgw1_prefix2': '10.62.0.0/16',
            'conn1': 'conn1'
        })

        self.cmd('network vnet create -g {rg} -n {vnet1} --address-prefix {vnet_prefix1} {vnet_prefix2}')
        self.cmd(
            'network vnet subnet create -g {rg} --vnet-name {vnet1} -n {fe_sub1} --address-prefix {fe_sub_prefix1} --default-outbound false')
        self.cmd(
            'network vnet subnet create -g {rg} --vnet-name {vnet1} -n {be_sub1} --address-prefix {be_sub_prefix1} --default-outbound false')
        self.cmd(
            'network vnet subnet create -g {rg} --vnet-name {vnet1} -n {gw_sub1} --address-prefix {gw_sub_prefix1} --default-outbound false')
        self.cmd('network public-ip create -g {rg} -n {gw1ip}')

        self.cmd(
            'network vnet-gateway create -g {rg} -l {location} -n {gw1} --public-ip-address {gw1ip} --vnet {vnet1} --sku {gw1_sku}')
        self.kwargs["local_gateway_id"] = self.cmd(
            'network local-gateway create -g {rg2} -l {location} -n {lgw1} --gateway-ip-address {lgw1ip} --local-address-prefixes {lgw1_prefix1} {lgw1_prefix2} --subscription {aux_sub}').get_output_in_json()["id"]

        self.cmd(
            'network vpn-connection create -g {rg} -l {location} -n {conn1} --vnet-gateway1 {gw1} --local-gateway2 {local_gateway_id} --shared-key AzureA1b2C3',
            checks=[
                self.check("resource.localNetworkGateway2.id", "{local_gateway_id}"),
            ]
        )

    @ResourceGroupPreparer(name_prefix='cli_test_vpn_connection_ipsec')
    def test_network_vpn_connection_ipsec(self, resource_group):

        self.kwargs.update({
            'vnet1': 'vnet1',
            'vnet_prefix1': '10.11.0.0/16',
            'vnet_prefix2': '10.12.0.0/16',
            'fe_sub1': 'FrontEnd',
            'fe_sub_prefix1': '10.11.0.0/24',
            'be_sub1': 'BackEnd',
            'be_sub_prefix1': '10.12.0.0/24',
            'gw_sub1': 'GatewaySubnet',
            'gw_sub_prefix1': '10.12.255.0/27',
            'gw1ip': 'pip1',
            'gw1': 'gw1',
            'gw1_sku': 'VpnGw1',
            'lgw1': 'lgw1',
            'lgw1ip': '131.107.72.22',
            'lgw1_prefix1': '10.61.0.0/16',
            'lgw1_prefix2': '10.62.0.0/16',
            'conn1': 'conn1'
        })

        self.cmd('network vnet create -g {rg} -n {vnet1} --address-prefix {vnet_prefix1} {vnet_prefix2}')
        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet1} -n {fe_sub1} --address-prefix {fe_sub_prefix1} --default-outbound false')
        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet1} -n {be_sub1} --address-prefix {be_sub_prefix1} --default-outbound false')
        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet1} -n {gw_sub1} --address-prefix {gw_sub_prefix1} --default-outbound false')
        self.cmd('network public-ip create -g {rg} -n {gw1ip}')

        self.cmd('network vnet-gateway create -g {rg} -n {gw1} --public-ip-address {gw1ip} --vnet {vnet1} --sku {gw1_sku}')
        self.cmd('network local-gateway create -g {rg} -n {lgw1} --gateway-ip-address {lgw1ip} --local-address-prefixes {lgw1_prefix1} {lgw1_prefix2}')
        self.cmd('network vpn-connection create -g {rg} -n {conn1} --vnet-gateway1 {gw1} --local-gateway2 {lgw1} --shared-key AzureA1b2C3')
        self.cmd('network vpn-connection list -g {rg}', checks=[
            self.check('length(@)', 1)
        ])
        self.cmd('network vpn-connection list -g {rg} --vnet-gateway {gw1}', checks=[
            self.check('length(@)', 1)
        ])

        # test vpn connection show
        self.cmd('network vpn-connection show -g {rg} -n {conn1}', checks=[
            self.check('name', 'conn1')
        ])
        # test vpn connection show-device-config-script
        self.cmd('network vpn-connection show-device-config-script -g {rg} -n {conn1} --vendor "Cisco" --device-family "Cisco-ISR(IOS)" --firmware-version "Cisco-ISR-15.x--IKEv2+BGP"')
        self.cmd('network vpn-connection ipsec-policy add -g {rg} --connection-name {conn1} --ike-encryption AES256 --ike-integrity SHA384 --dh-group DHGroup24 --ipsec-encryption GCMAES256 --ipsec-integrity GCMAES256 --pfs-group PFS24 --sa-lifetime 7200 --sa-max-size 2048')
        self.cmd('network vpn-connection ipsec-policy list -g {rg} --connection-name {conn1}', checks=self.check('length(@)', 1))
        self.cmd('network vpn-connection ipsec-policy clear -g {rg} --connection-name {conn1}')
        self.cmd('network vpn-connection ipsec-policy list -g {rg} --connection-name {conn1}', checks=self.check('length(@)', 0))


class NetworkVpnConnectionNatRule(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='test_network_vpn_connection_nat_rule')
    def test_network_vpn_connection_nat_rule(self, resource_group):

        self.kwargs.update({
            'vnet': 'vnet',
            'lgw1': 'lgw1',
            'lgw1ip': '131.107.72.22',
            'lgw1_prefix1': '10.61.0.0/16',
            'lgw1_prefix2': '10.62.0.0/16',
            'conn1': 'conn1',
            'subnet': 'GatewaySubnet',
            'vg': 'vnet-gateway-name',
            'ip': 'ip-name',
            'sku': 'VpnGw2',
            'nat': 'nat-name',
            'nat1': 'nat-name1',
            'i_map': '10.4.0.0/24',
            'i_map1': '10.5.0.0/24',
            'e_map': '192.168.21.0/24',
            'e_map1': '192.168.22.0/24',
        })

        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name {subnet}')
        self.cmd('network public-ip create -g {rg} -n {ip}')

        vg = self.cmd('network vnet-gateway create -g {rg} -n {vg} --vnet {vnet} --public-ip-address {ip} --sku {sku} '
                      '--nat-rule name={nat} mode=IngressSnat internal-mappings={i_map} external-mappings={e_map} '
                      '--nat-rule name={nat1} mode=EgressSnat internal-mappings={i_map1} external-mappings={e_map1}',
                      checks=[self.check('length(vnetGateway.natRules)', 2)]).get_output_in_json()

        self.kwargs.update({'id': vg['vnetGateway']['natRules'][0]['id']})
        self.kwargs.update({'id1': vg['vnetGateway']['natRules'][1]['id']})

        self.cmd('network local-gateway create -g {rg} -n {lgw1} --gateway-ip-address {lgw1ip} '
                 '--local-address-prefixes {lgw1_prefix1} {lgw1_prefix2}')
        self.cmd('network vpn-connection create -g {rg} -n {conn1} --vnet-gateway1 {vg} --local-gateway2 {lgw1} '
                 '--shared-key AzureA1b2C3 --ingress-nat-rule {id}',
                 checks=[self.check('length(resource.ingressNatRules)', 1)])

        self.cmd('network vpn-connection delete -g {rg} -n {conn1}')

        self.cmd('network vpn-connection create -g {rg} -n {conn1} --vnet-gateway1 {vg} --local-gateway2 {lgw1} '
                 '--shared-key AzureA1b2C3 --egress-nat-rule {id1}',
                 checks=[self.check('length(resource.egressNatRules)', 1)])


class VNetGatewayManagedIdentityScenarioTest(ScenarioTest):
    @ResourceGroupPreparer(location='eastus', name_prefix='test_vnet_gateway_mi')
    @AllowLargeResponse(size_kb=9999)
    def test_vnet_gateway_managed_identity(self, resource_group):
        subscription_id = self.get_subscription_id()
        self.kwargs.update({
            'rg': resource_group,
            'identity_name': 'myUamIdentity',
            'identity_name_2': 'myUamIdentity2',
            'vnet_name': 'myVNet',
            'pip_name': 'myGWpip',
            'gateway_name': 'myTestGW',
            'subscription': subscription_id,
            'location': 'eastus'
        })

        # create managed identity 1
        identity_result = self.cmd('identity create -g {rg} -n {identity_name}', checks=[
            self.check('name', '{identity_name}'),
            self.check('location', '{location}'),
            self.exists('clientId'),
            self.exists('principalId'),
            self.exists('id')
        ]).get_output_in_json()
        self.kwargs['identity_id'] = identity_result['id']

        # create managed identity 2 (for update test)
        identity_result_2 = self.cmd('identity create -g {rg} -n {identity_name_2}', checks=[
            self.check('name', '{identity_name_2}'),
            self.check('location', '{location}'),
            self.exists('clientId'),
            self.exists('principalId'),
            self.exists('id')
        ]).get_output_in_json()
        self.kwargs['identity_id_2'] = identity_result_2['id']

        # create vnet with subnet
        self.cmd('network vnet create -g {rg} -n {vnet_name} '
                '--address-prefix 10.0.0.0/16 '
                '--subnet-name GatewaySubnet '
                '--subnet-prefix 10.0.255.0/24', checks=[
            self.check('newVNet.name', '{vnet_name}'),
            self.check('newVNet.addressSpace.addressPrefixes[0]', '10.0.0.0/16'),
            self.check('newVNet.subnets[0].name', 'GatewaySubnet'),
            self.check('newVNet.subnets[0].addressPrefix', '10.0.255.0/24')
        ])

        # create public ip
        self.cmd('network public-ip create -g {rg} -n {pip_name} '
                '--allocation-method Static '
                '--sku Standard '
                '--ip-tags FirstPartyUsage=/NonProd '
                '--zone 1 2 3', checks=[
            self.check('publicIp.name', '{pip_name}'),
            self.check('publicIp.publicIPAllocationMethod', 'Static'),
            self.check('publicIp.sku.name', 'Standard'),
            self.check('length(publicIp.zones)', 3)
        ])

        # create vnet-gateway with user-assigned managed identity
        self.cmd('network vnet-gateway create -g {rg} -n {gateway_name} '
                '--public-ip-address {pip_name} '
                '--vnet {vnet_name} '
                '--gateway-type Vpn '
                '--vpn-type RouteBased '
                '--sku VpnGw2AZ '
                '--mi-user-assigned {identity_id}', checks=[
            self.check('vnetGateway.name', '{gateway_name}'),
            self.check('vnetGateway.gatewayType', 'Vpn'),
            self.check('vnetGateway.vpnType', 'RouteBased'),
            self.check('vnetGateway.sku.name', 'VpnGw2AZ'),
            self.check('vnetGateway.sku.tier', 'VpnGw2AZ'),
            self.check('vnetGateway.identity.type', 'userAssigned'),
            self.exists('vnetGateway.identity.userAssignedIdentities')
        ])

        # verify identity configuration
        self.cmd('network vnet-gateway show -g {rg} -n {gateway_name}', checks=[
            self.check('name', '{gateway_name}'),
            self.check('identity.type', 'userAssigned'),
            self.exists('identity.userAssignedIdentities')
        ])

        identity_show_result = self.cmd('network vnet-gateway identity show -g {rg} -n {gateway_name}', checks=[
            self.check('type', 'userAssigned'),
            self.exists('userAssignedIdentities')
        ]).get_output_in_json()

        # Verify the first user-assigned identity details
        assert self.kwargs['identity_id'] in identity_show_result['userAssignedIdentities']

        # update vnet-gateway to use a different managed identity
        # Note: VPN Gateway currently only allows one user-assigned identity at a time,
        # so we need to remove the existing identity before assigning a new one
        self.cmd('network vnet-gateway identity remove -g {rg} -n {gateway_name} --user-assigned', checks=[
            self.check('type', 'none')
        ])

        # Then assign the new identity
        self.cmd('network vnet-gateway identity assign -g {rg} -n {gateway_name} '
                 '--user-assigned {identity_id_2}', checks=[
            self.check('type', 'userAssigned'),
            self.exists('userAssignedIdentities')
        ])

        # verify the identity was updated to the second identity
        identity_show_result_updated = self.cmd('network vnet-gateway identity show -g {rg} -n {gateway_name}', checks=[
            self.check('type', 'userAssigned'),
            self.exists('userAssignedIdentities')
        ]).get_output_in_json()

        # verify the second user-assigned identity is now configured
        assert self.kwargs['identity_id_2'] in identity_show_result_updated['userAssignedIdentities']

        # remove user-assigned identity
        self.cmd('network vnet-gateway identity remove -g {rg} -n {gateway_name} --user-assigned', checks=[
            self.check('type', 'none')
        ])

        # double check identity is really deleted
        self.cmd('network vnet-gateway show -g {rg} -n {gateway_name}', checks=[
            self.check('name', '{gateway_name}'),
            self.check('identity.type', 'none'),
            self.check('provisioningState', 'Succeeded')
        ])

        # verify identity show returns none type
        self.cmd('network vnet-gateway identity show -g {rg} -n {gateway_name}', checks=[
            self.check('type', 'none')
        ])

        # update to add identity back (testing update from none to userAssigned)
        self.cmd('network vnet-gateway identity assign -g {rg} -n {gateway_name} '
                 '--user-assigned {identity_id}', checks=[
            self.check('type', 'userAssigned'),
            self.exists('userAssignedIdentities')
        ])

        self.cmd('network vnet-gateway identity show -g {rg} -n {gateway_name}', checks=[
            self.check('type', 'userAssigned'),
            self.exists('userAssignedIdentities')
        ])

        self.cmd('network vnet-gateway delete -g {rg} -n {gateway_name}')

        self.cmd('network vnet-gateway list -g {rg}', checks=[
            self.check('length(@)', 0)
        ])


class VpnConnectionAuthenticationScenarioTest(ScenarioTest):

    @staticmethod
    def _get_now_utc():
        import datetime
        try:
            from datetime import timezone
            return datetime.datetime.now(timezone.utc)
        except ImportError:
            return datetime.datetime.utcnow()

    @staticmethod
    def _format_subject_dn(common_name: str):
        return "CN={}, OU=IT, O=Test Organization, L=Redmond, S=Washington, C=US".format(common_name)

    @staticmethod
    def generate_ca_chain(root_cert_path, intermediate_cert_path):
        """
        Generate a valid certificate chain:
          Root CA -> Intermediate CA
        Return: (root_key, root_cert, inter_key, inter_cert)
        """
        try:
            from cryptography import x509
            from cryptography.x509.oid import NameOID
            from cryptography.hazmat.primitives import hashes, serialization
            from cryptography.hazmat.primitives.asymmetric import rsa
            from cryptography.hazmat.backends import default_backend
            import datetime

            now = VpnConnectionAuthenticationScenarioTest._get_now_utc()

            os.makedirs(os.path.dirname(root_cert_path), exist_ok=True)

            # ===== Root CA =====
            root_key = rsa.generate_private_key(
                public_exponent=65537,
                key_size=2048,
                backend=default_backend()
            )

            root_subject = x509.Name([
                x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
                x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Washington"),
                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Test Root CA Org"),
                x509.NameAttribute(NameOID.COMMON_NAME, u"Test Root CA"),
            ])

            root_public_key = root_key.public_key()
            root_ski = x509.SubjectKeyIdentifier.from_public_key(root_public_key)

            root_cert = x509.CertificateBuilder().subject_name(
                root_subject
            ).issuer_name(
                root_subject
            ).public_key(
                root_public_key
            ).serial_number(
                x509.random_serial_number()
            ).not_valid_before(
                now - datetime.timedelta(minutes=5)
            ).not_valid_after(
                now + datetime.timedelta(days=3650)
            ).add_extension(
                x509.BasicConstraints(ca=True, path_length=1),
                critical=True,
            ).add_extension(
                x509.KeyUsage(
                    digital_signature=True,
                    key_cert_sign=True,
                    crl_sign=True,
                    key_encipherment=False,
                    content_commitment=False,
                    data_encipherment=False,
                    key_agreement=False,
                    encipher_only=False,
                    decipher_only=False,
                ),
                critical=True,
            ).add_extension(
                root_ski,
                critical=False,
            ).sign(root_key, hashes.SHA256(), default_backend())

            # Write Root cert (public only)
            with open(root_cert_path, 'wb') as f:
                f.write(root_cert.public_bytes(serialization.Encoding.PEM))

            # ===== Intermediate CA (signed by Root) =====
            intermediate_key = rsa.generate_private_key(
                public_exponent=65537,
                key_size=2048,
                backend=default_backend()
            )

            intermediate_subject = x509.Name([
                x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
                x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Washington"),
                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Test Intermediate CA Org"),
                x509.NameAttribute(NameOID.COMMON_NAME, u"Test Intermediate CA"),
            ])

            intermediate_public_key = intermediate_key.public_key()
            intermediate_ski = x509.SubjectKeyIdentifier.from_public_key(intermediate_public_key)
            intermediate_aki = x509.AuthorityKeyIdentifier.from_issuer_public_key(root_public_key)

            intermediate_cert = x509.CertificateBuilder().subject_name(
                intermediate_subject
            ).issuer_name(
                root_subject
            ).public_key(
                intermediate_public_key
            ).serial_number(
                x509.random_serial_number()
            ).not_valid_before(
                now - datetime.timedelta(minutes=5)
            ).not_valid_after(
                now + datetime.timedelta(days=1825)
            ).add_extension(
                x509.BasicConstraints(ca=True, path_length=0),
                critical=True,
            ).add_extension(
                x509.KeyUsage(
                    digital_signature=True,
                    key_cert_sign=True,
                    crl_sign=True,
                    key_encipherment=False,
                    content_commitment=False,
                    data_encipherment=False,
                    key_agreement=False,
                    encipher_only=False,
                    decipher_only=False,
                ),
                critical=True,
            ).add_extension(
                intermediate_ski,
                critical=False,
            ).add_extension(
                intermediate_aki,
                critical=False,
            ).sign(root_key, hashes.SHA256(), default_backend())

            # Write Intermediate cert (public only)
            with open(intermediate_cert_path, 'wb') as f:
                f.write(intermediate_cert.public_bytes(serialization.Encoding.PEM))

            return root_key, root_cert, intermediate_key, intermediate_cert

        except ImportError as e:
            raise Exception(f"cryptography package is required. Error: {e}")

    @staticmethod
    def generate_leaf_certificate(common_name, signer_key, signer_cert, is_ca=False, days=365):
        """
        Generate a leaf certificate signed by signer_cert.
        Return: (leaf_private_key, leaf_cert)
        """
        try:
            from cryptography import x509
            from cryptography.x509.oid import NameOID, ExtendedKeyUsageOID
            from cryptography.hazmat.primitives import hashes
            from cryptography.hazmat.primitives.asymmetric import rsa
            from cryptography.hazmat.backends import default_backend
            import datetime

            now = VpnConnectionAuthenticationScenarioTest._get_now_utc()

            private_key = rsa.generate_private_key(
                public_exponent=65537,
                key_size=2048,
                backend=default_backend()
            )

            subject = x509.Name([
                x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
                x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Washington"),
                x509.NameAttribute(NameOID.LOCALITY_NAME, u"Redmond"),
                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Test Organization"),
                x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"IT"),
                x509.NameAttribute(NameOID.COMMON_NAME, common_name),
            ])

            public_key = private_key.public_key()
            ski = x509.SubjectKeyIdentifier.from_public_key(public_key)
            aki = x509.AuthorityKeyIdentifier.from_issuer_public_key(signer_key.public_key())

            builder = x509.CertificateBuilder().subject_name(
                subject
            ).issuer_name(
                signer_cert.subject
            ).public_key(
                public_key
            ).serial_number(
                x509.random_serial_number()
            ).not_valid_before(
                now - datetime.timedelta(minutes=5)
            ).not_valid_after(
                now + datetime.timedelta(days=days)
            )

            # Leaf cert constraints
            builder = builder.add_extension(
                x509.BasicConstraints(ca=is_ca, path_length=None if not is_ca else 0),
                critical=True,
            )

            # EKU: Both client & server auth are required for certificate auth
            builder = builder.add_extension(
                x509.ExtendedKeyUsage([
                    ExtendedKeyUsageOID.SERVER_AUTH,
                    ExtendedKeyUsageOID.CLIENT_AUTH,
                ]),
                critical=False,
            )

            # Key usage for leaf
            builder = builder.add_extension(
                x509.KeyUsage(
                    digital_signature=True,
                    key_encipherment=True,
                    key_cert_sign=False,
                    crl_sign=False,
                    content_commitment=False,
                    data_encipherment=False,
                    key_agreement=False,
                    encipher_only=False,
                    decipher_only=False,
                ),
                critical=True,
            )

            builder = builder.add_extension(ski, critical=False)
            builder = builder.add_extension(aki, critical=False)

            cert = builder.sign(signer_key, hashes.SHA256(), default_backend())
            return private_key, cert

        except ImportError as e:
            raise Exception(f"cryptography package (>= 3.0) is required for certificate generation. "
                            f"Install it with: pip install 'cryptography>=3.0'. Error: {e}")

    @staticmethod
    def write_pem_cert(cert, cert_path):
        try:
            from cryptography.hazmat.primitives import serialization
            os.makedirs(os.path.dirname(cert_path), exist_ok=True)
            with open(cert_path, 'wb') as f:
                f.write(cert.public_bytes(serialization.Encoding.PEM))
        except ImportError as e:
            raise Exception(f"cryptography package is required. Error: {e}")

    @staticmethod
    def generate_outbound_pfx_with_chain(pfx_path, password, leaf_private_key, leaf_cert, chain_certs):
        """
        Generate outbound PFX that includes:
          - leaf cert + private key
          - CA chain (intermediate + root) via 'cas'
        """
        try:
            from cryptography.hazmat.primitives import serialization
            from cryptography.hazmat.primitives.serialization.pkcs12 import serialize_key_and_certificates, load_key_and_certificates

            os.makedirs(os.path.dirname(pfx_path), exist_ok=True)

            pfx_data = serialize_key_and_certificates(
                name=b"test-vpn-outbound",
                key=leaf_private_key,
                cert=leaf_cert,
                cas=chain_certs,  # IMPORTANT: include CA chain
                encryption_algorithm=serialization.BestAvailableEncryption(password.encode())
            )

            with open(pfx_path, 'wb') as f:
                f.write(pfx_data)

            _k, _c, _addl = load_key_and_certificates(pfx_data, password.encode())

        except ImportError as e:
            raise Exception(f"cryptography package is required for PFX generation. Error: {e}")

    @live_only()
    @ResourceGroupPreparer(location='eastus', name_prefix='test_vpn_connection_auth')
    @KeyVaultPreparer(name_prefix='cli-mi-vpn-cert-kv-', sku='premium',
                      additional_params='--enable-rbac-authorization false')
    @AllowLargeResponse(size_kb=9999)
    def test_vpn_connection_authentication(self, resource_group):
        import json
        import tempfile
        import shutil

        subscription_id = self.get_subscription_id()
        self.kwargs.update({
            'rg': resource_group,
            'location': 'eastus',
            'vnet_name': 'myVNet',
            'vnet_gateway_name': 'myVnetGateway',
            'local_gateway_name': 'myLocalGateway',
            'pip_name': 'myGatewayIP',
            'connection_name': 'myVpnConnection',
            'identity_name': 'myIdentity',
            'cert_name': 'vpn-gateway-cert',
            'shared_key': 'Abc123',
            'subscription': subscription_id
        })

        # create temporary directory for test certificates
        temp_dir = tempfile.mkdtemp()
        outbound_cert_path = os.path.join(temp_dir, 'VpnGatewayoutboundcert.pfx')

        # public cert files for inbound chain (PEM with BEGIN/END CERT)
        inbound_cert1_path = os.path.join(temp_dir, 'VpnGatewayInboundCert.cer')  # Intermediate CA (public)
        inbound_cert2_path = os.path.join(temp_dir, 'VpnGatewayAuthCert.cer')    # Root CA (public)

        try:
            root_key, root_cert, inter_key, inter_cert = self.generate_ca_chain(
                root_cert_path=inbound_cert2_path,          # Root CA public
                intermediate_cert_path=inbound_cert1_path    # Intermediate CA public
            )

            outbound_cn = "test-vpn-outbound.local"
            outbound_key, outbound_leaf_cert = self.generate_leaf_certificate(
                common_name=outbound_cn,
                signer_key=inter_key,
                signer_cert=inter_cert
            )
            self.generate_outbound_pfx_with_chain(
                pfx_path=outbound_cert_path,
                password="AAAAAAAA",
                leaf_private_key=outbound_key,
                leaf_cert=outbound_leaf_cert,
                chain_certs=[inter_cert, root_cert]  # include chain
            )

            # generate inbound leaf cert (signed by Intermediate)
            inbound_cn = "test-vpn-inbound.local"
            _in_key, inbound_leaf_cert = self.generate_leaf_certificate(
                common_name=inbound_cn,
                signer_key=inter_key,
                signer_cert=inter_cert
            )
            self.kwargs['subject_name'] = self._format_subject_dn(inbound_cn)

            # create managed identity
            identity_result = self.cmd('identity create -g {rg} -n {identity_name}', checks=[
                self.check('name', '{identity_name}'),
                self.exists('principalId')
            ]).get_output_in_json()
            self.kwargs['identity_id'] = identity_result['id']
            self.kwargs['principal_id'] = identity_result['principalId']

            # grant managed identity access to KV
            self.cmd('keyvault set-policy -n {kv} '
                     '--object-id {principal_id} '
                     '--certificate-permissions get list '
                     '--secret-permissions get list')

            # import outbound certificate to KV
            self.cmd(f'keyvault certificate import -n {{cert_name}} --vault-name {{kv}} '
                     f'--file "{outbound_cert_path}" --password "AAAAAAAA"', checks=[
                self.check('name', '{cert_name}')
            ])

            # get certificate url (OutboundAuthCertificate)
            cert_info = self.cmd('keyvault certificate show -n {cert_name} --vault-name {kv}').get_output_in_json()
            self.kwargs['cert_url'] = cert_info['id']

            # read inbound certificate chain (public keys only)
            # Azure docs recommend at least two certs (Root + Intermediate)
            def read_cert_base64(file_path):
                with open(file_path, 'r') as f:
                    content = f.read()
                cert_data = content.replace('-----BEGIN CERTIFICATE-----', '')
                cert_data = cert_data.replace('-----END CERTIFICATE-----', '')
                cert_data = cert_data.replace('\n', '').replace('\r', '').strip()
                return cert_data

            inbound_root_base64 = read_cert_base64(inbound_cert2_path)
            inbound_intermediate_base64 = read_cert_base64(inbound_cert1_path)

            # create virtual network with gateway subnet
            self.cmd('network vnet create -g {rg} -n {vnet_name} '
                     '--address-prefix 10.0.0.0/16 '
                     '--subnet-name GatewaySubnet '
                     '--subnet-prefix 10.0.255.0/24', checks=[
                self.check('newVNet.name', '{vnet_name}'),
                self.check('newVNet.subnets[0].name', 'GatewaySubnet')
            ])

            # create public ip
            self.cmd('network public-ip create -g {rg} -n {pip_name} '
                     '--allocation-method Static '
                     '--ip-tags FirstPartyUsage=/NonProd '
                     '--sku Standard', checks=[
                self.check('publicIp.name', '{pip_name}')
            ])

            # create vnet gateway with managed identity
            self.cmd('network vnet-gateway create -g {rg} -n {vnet_gateway_name} '
                     '--public-ip-address {pip_name} '
                     '--vnet {vnet_name} '
                     '--gateway-type Vpn '
                     '--vpn-type RouteBased '
                     '--sku VpnGw1 '
                     '--mi-user-assigned {identity_id}', checks=[
                self.check('vnetGateway.name', '{vnet_gateway_name}'),
                self.check('vnetGateway.gatewayType', 'Vpn'),
                self.exists('vnetGateway.identity')
            ])

            # create local gateway
            self.cmd('network local-gateway create -g {rg} -n {local_gateway_name} '
                     '--gateway-ip-address 192.168.4.5 '
                     '--local-address-prefixes 192.168.0.0/16', checks=[
                self.check('name', '{local_gateway_name}')
            ])

            # create vpn connection with certificate authentication
            cert_auth_config = {
                "outboundAuthCertificate": self.kwargs['cert_url'],
                "inboundAuthCertificateChain": [inbound_root_base64, inbound_intermediate_base64],
                "inboundAuthCertificateSubjectName": self.kwargs['subject_name']
            }
            self.kwargs['cert_auth'] = json.dumps(cert_auth_config)
            self.cmd('network vpn-connection create -g {rg} -n {connection_name} '
                     '--vnet-gateway1 {vnet_gateway_name} '
                     '--local-gateway2 {local_gateway_name} '
                     '--shared-key {shared_key} '
                     '--auth-type Certificate '
                     '--cert-auth \'{cert_auth}\'', checks=[
                self.check('resource.connectionType', 'IPsec')
            ])

            # verify connection with certificate authentication
            connection = self.cmd('network vpn-connection show -g {rg} -n {connection_name}', checks=[
                self.check('name', '{connection_name}'),
                self.check('authenticationType', 'Certificate'),
                self.exists('certificateAuthentication')
            ]).get_output_in_json()

            # verify certificate authentication configuration
            cert_config = connection['certificateAuthentication']
            self.assertEqual(cert_config['outboundAuthCertificate'], self.kwargs['cert_url'])
            self.assertEqual(cert_config['inboundAuthCertificateSubjectName'], self.kwargs['subject_name'])
            self.assertEqual(len(cert_config['inboundAuthCertificateChain']), 2)

            # update certificate authentication
            new_cert_auth_config = {
                "outboundAuthCertificate": self.kwargs['cert_url'],
                "inboundAuthCertificateChain": [inbound_root_base64, inbound_intermediate_base64],
                "inboundAuthCertificateSubjectName": self.kwargs['subject_name'] + "-new"
            }
            self.kwargs['new_cert_auth'] = json.dumps(new_cert_auth_config)
            self.cmd('network vpn-connection update -g {rg} -n {connection_name} '
                     '--cert-auth \'{new_cert_auth}\'', checks=[
                self.check('name', '{connection_name}'),
                self.check('authenticationType', 'Certificate')
            ])

            # delete connection
            self.cmd('network vpn-connection delete -g {rg} -n {connection_name}')

            # create connection with PSK for comparison
            self.cmd('network vpn-connection create -g {rg} -n {connection_name} '
                     '--vnet-gateway1 {vnet_gateway_name} '
                     '--local-gateway2 {local_gateway_name} '
                     '--shared-key {shared_key}')

            # verify PSK connection
            psk_connection = self.cmd('network vpn-connection show -g {rg} -n {connection_name}').get_output_in_json()
            if 'authenticationType' in psk_connection:
                self.assertIn(psk_connection['authenticationType'], ['PSK', None])

        finally:
            # clean up temporary certificates
            if os.path.exists(temp_dir):
                shutil.rmtree(temp_dir)


class NetworkVnetGatewayIpSecPolicy(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_vnet_gateway_ipsec')
    def test_network_vnet_gateway_ipsec(self, resource_group):
        self.kwargs.update({
            'vnet': 'vnet1',
            'ip': 'pip1',
            'gw': 'gw1',
            'gw_sku': 'VpnGw2',
        })

        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name GatewaySubnet')
        self.cmd('network public-ip create -g {rg} -n {ip}')
        self.cmd('network vnet-gateway create -g {rg} -n {gw} --public-ip-address {ip} --vnet {vnet} '
                 '--sku {gw_sku} --gateway-type Vpn --vpn-type RouteBased '
                 '--address-prefix 172.16.0.0/24 --client-protocol IkeV2')
        self.cmd('network vnet-gateway ipsec-policy add -g {rg} --gateway-name {gw} '
                 '--ike-encryption AES256 --ike-integrity SHA384 --dh-group DHGroup24 '
                 '--ipsec-encryption GCMAES256 --ipsec-integrity GCMAES256 --pfs-group PFS24 '
                 '--sa-lifetime 7200 --sa-max-size 2048',
                 checks=[self.check('dhGroup', 'DHGroup24'),
                         self.check('ikeEncryption', 'AES256'),
                         self.check('ikeIntegrity', 'SHA384'),
                         self.check('ipsecEncryption', 'GCMAES256'),
                         self.check('ipsecIntegrity', 'GCMAES256'),
                         self.check('pfsGroup', 'PFS24'),
                         self.check('saDataSizeKilobytes', 2048),
                         self.check('saLifeTimeSeconds', 7200)])

        self.cmd('network vnet-gateway ipsec-policy list -g {rg} --gateway-name {gw}',
                 checks=[self.check('length(@)', 1)])
        self.cmd('network vnet-gateway ipsec-policy clear -g {rg} --gateway-name {gw}')
        self.cmd('network vnet-gateway ipsec-policy list -g {rg} --gateway-name {gw}',
                 checks=[self.check('length(@)', 0)])
        self.cmd('network vnet-gateway vpn-client show-health -g {rg} -n {gw}')
        self.cmd('network vnet-gateway show-supported-devices -g {rg} -n {gw} -o tsv')


class NetworkVnetGatewayMigration(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_vnet_gateway_migration', location='westus')
    def test_network_vnet_gateway_migration(self, resource_group):
        self.kwargs.update({
            'vnet': 'vnet1',
            'pub_ip': 'public_ip1',
            'gw': 'gateway1',
        })

        self.cmd('network vnet create -g {rg} -n {vnet} --address-prefix 10.0.0.0/16 --subnet-name GatewaySubnet --subnet-prefix 10.0.0.0/24')
        self.cmd('network public-ip create -g {rg} -n {pub_ip} --sku Basic')
        self.cmd('network vnet-gateway create -g {rg} -n {gw} --sku VpnGw1 --vpn-gateway-generation Generation1 '
                 '--vnet {vnet} --public-ip-address {pub_ip} --vpn-type RouteBased', 
                 checks=[
                    self.check('virtualNetworkGatewayMigrationStatus.state', None),
                    self.check('virtualNetworkGatewayMigrationStatus.phase', None)
        ])

        # prepare migration
        self.cmd('network vnet-gateway migration prepare -g {rg} -n {gw} --migration-type UpgradeDeploymentToStandardIP')
        self.cmd('network vnet-gateway show -g {rg} -n {gw}', checks=[
            self.check('virtualNetworkGatewayMigrationStatus.state', 'InProgress'),
            self.check('virtualNetworkGatewayMigrationStatus.phase', 'PrepareSucceeded')
        ])

        # execute migration
        self.cmd('network vnet-gateway migration execute -g {rg} -n {gw}')
        self.cmd('network vnet-gateway show -g {rg} -n {gw}', checks=[
            self.check('virtualNetworkGatewayMigrationStatus.state', 'InProgress'),
            self.check('virtualNetworkGatewayMigrationStatus.phase', 'ExecuteSucceeded')
        ])

        # commit migration
        self.cmd('network vnet-gateway migration commit -g {rg} -n {gw}')
        self.cmd('network vnet-gateway show -g {rg} -n {gw}', checks=[
            self.check('virtualNetworkGatewayMigrationStatus.state', 'Succeeded'),
            self.check('virtualNetworkGatewayMigrationStatus.phase', 'CommitSucceeded')
        ])


class NetworkVnetGatewayMultiAuth(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='test_network_vnet_gateway_multi_auth')
    def test_network_vnet_gateway_multi_auth(self, resource_group):

        self.kwargs.update({
            'vnet': 'vnet',
            'ip': 'pip',
            'gw': 'gw',
            'gw_sku': 'VpnGw2',
            'aad_tenant': 'https://login.microsoftonline.com/0ab2c4f4-81e6-44cc-a0b2-b3a47a1443f4',
            'aad_issuer': 'https://sts.windows.net/0ab2c4f4-81e6-44cc-a0b2-b3a47a1443f4/',
            'aad_audience': 'a21fce82-76af-45e6-8583-a08cb3b956f9',
            'root_cert_name': 'root-cert',
            'root_cert_data': os.path.join(TEST_DIR, 'test-root-cert.cer'),
        })
        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name GatewaySubnet')
        self.cmd('network public-ip create -g {rg} -n {ip}')
        self.cmd('network vnet-gateway create -g {rg} -n {gw} --public-ip-address {ip} --vnet {vnet} --sku {gw_sku} '
                 '--gateway-type Vpn --vpn-type RouteBased --address-prefix 40.1.0.0/24 --client-protocol OpenVPN '
                 '--aad-audience {aad_audience} --aad-issuer {aad_issuer} --aad-tenant {aad_tenant} '
                 '--root-cert-name {root_cert_name} --root-cert-data "{root_cert_data}" '
                 '--radius-secret 111_aaa --radius-server 30.1.1.15 --vpn-auth-type AAD Certificate Radius',
                 checks=[self.check('length(vnetGateway.vpnClientConfiguration.vpnAuthenticationTypes)', 3)])

    @ResourceGroupPreparer(name_prefix='test_network_vnet_gateway_multi_auth1')
    def test_network_vnet_gateway_multi_auth1(self, resource_group):

        self.kwargs.update({
            'vnet': 'vnet',
            'ip': 'pip',
            'gw': 'gw',
            'gw_sku': 'VpnGw2',
            'aad_tenant': 'https://login.microsoftonline.com/0ab2c4f4-81e6-44cc-a0b2-b3a47a1443f4',
            'aad_issuer': 'https://sts.windows.net/0ab2c4f4-81e6-44cc-a0b2-b3a47a1443f4/',
            'aad_audience': 'a21fce82-76af-45e6-8583-a08cb3b956f9',
            'root_cert_name': 'root-cert',
            'root_cert_data': os.path.join(TEST_DIR, 'test-root-cert.cer'),
        })

        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name GatewaySubnet')
        self.cmd('network public-ip create -g {rg} -n {ip}')
        self.cmd('network vnet-gateway create -g {rg} -n {gw} --public-ip-address {ip} --vnet {vnet} --sku {gw_sku} '
                 '--gateway-type Vpn --vpn-type RouteBased --address-prefix 40.1.0.0/24 --client-protocol OpenVPN')
        self.cmd('network vnet-gateway update -g {rg} -n {gw} --vpn-auth-type AAD Certificate Radius '
                 '--aad-audience {aad_audience} --aad-issuer {aad_issuer} --aad-tenant {aad_tenant} '
                 '--root-cert-name {root_cert_name} --root-cert-data "{root_cert_data}" '
                 '--radius-secret 111_aaa --radius-server 30.1.1.15',
                 checks=[self.check('length(vpnClientConfiguration.vpnAuthenticationTypes)', 3)])

    @ResourceGroupPreparer(name_prefix='test_network_vnet_gateway_allow_traffic')
    def test_network_vnet_gateway_allow_traffic(self, resource_group):
        self.kwargs.update({
            'vnet': 'vnet',
            'ip': 'pip',
            'gw': 'gw',
            'gw_sku': 'VpnGw2',
        })

        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name GatewaySubnet')
        self.cmd('network public-ip create -g {rg} -n {ip}')
        self.cmd('network vnet-gateway create -g {rg} -n {gw} --public-ip-address {ip} --vnet {vnet} --sku {gw_sku} '
                 '--gateway-type Vpn --vpn-type RouteBased --address-prefix 40.1.0.0/24 --client-protocol OpenVPN '
                 '--allow-remote-vnet-traffic true --allow-vwan-traffic true',
                 checks=[self.check('vnetGateway.allowRemoteVnetTraffic', True),
                         self.check('vnetGateway.allowVirtualWanTraffic', True)])
        self.cmd('network vnet-gateway update -g {rg} -n {gw} --allow-remote-vnet-traffic false --allow-vwan-traffic false',
                 checks=[self.check('allowRemoteVnetTraffic', False),
                         self.check('allowVirtualWanTraffic', False)])


class NetworkExpressRouteGatewayScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='test_network_vnet_gateway_no_pip')
    def test_network_vnet_gateway_expressroute_without_public_ip(self, resource_group):

        self.kwargs.update({
            'vnet': 'vnet',
            'gw': 'gw',
            'sku': 'Standard',
        })

        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name GatewaySubnet')
        result = self.cmd('network vnet-gateway create -g {rg} -n {gw} --vnet {vnet} '
                          '--gateway-type ExpressRoute --sku {sku}').get_output_in_json()

        ip_configs = result['vnetGateway']['ipConfigurations']
        self.assertEqual(1, len(ip_configs))

        ip_config = ip_configs[0]
        self.assertEqual('Dynamic', ip_config['privateIPAllocationMethod'])
        self.assertTrue(ip_config['subnet']['id'].endswith('/subnets/GatewaySubnet'))
        self.assertFalse(ip_config.get('publicIPAddress'))

    @ResourceGroupPreparer(name_prefix='test_network_vnet_gateway_with_pip')
    def test_network_vnet_gateway_expressroute_with_public_ip(self, resource_group):

        self.kwargs.update({
            'vnet': 'vnet',
            'pip': 'pip',
            'gw': 'gw',
            'sku': 'Standard',
        })

        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name GatewaySubnet')
        public_ip = self.cmd('network public-ip create -g {rg} -n {pip}').get_output_in_json()['publicIp']['id']
        self.kwargs['pip_id'] = public_ip
        print(self.kwargs['pip_id'])
        result = self.cmd('network vnet-gateway create -g {rg} -n {gw} --vnet {vnet} '
                          '--gateway-type ExpressRoute --sku {sku} --public-ip-addresses {pip}').get_output_in_json()

        ip_configs = result['vnetGateway']['ipConfigurations']
        self.assertEqual(1, len(ip_configs))

        ip_config = ip_configs[0]
        print(ip_config)
        self.assertEqual('Dynamic', ip_config['privateIPAllocationMethod'])
        self.assertTrue(ip_config['subnet']['id'].endswith('/subnets/GatewaySubnet'))
        # public ip is ommitted by design with auto-assigned ip
        self.assertFalse(ip_config.get('publicIPAddress'))


class NetworkVirtualRouter(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_virtual_router', location='WestCentralUS')
    @unittest.skip('Skip as service has bug for deleting peering')
    def test_network_virtual_router_scenario(self, resource_group, resource_group_location):

        self.kwargs.update({
            'rg': resource_group,
            'location': resource_group_location,
            'vnet': 'vnet1',
            'ip': 'pip1',
            'gw': 'gw1',
            'gw_sku': 'HighPerformance',
            'vrouter': 'vrouter1',
            'vrouter_peering': 'peering1'
        })

        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name GatewaySubnet -l {location} --subnet-name GatewaySubnet')
        self.cmd('network public-ip create -g {rg} -n {ip} -l {location}')
        self.cmd('network vnet-gateway create -g {rg} -n {gw} --public-ip-address {ip} --vnet {vnet} --sku {gw_sku} --gateway-type ExpressRoute -l {location}')

        self.cmd('network vrouter create -n {vrouter} -l {location} -g {rg} --hosted-gateway {gw}', checks=[
            self.check('type', 'Microsoft.Network/VirtualRouters'),
            self.check('name', '{vrouter}')
        ])

        self.cmd('network vrouter show -n {vrouter} -g {rg}', checks=[
            self.check('name', '{vrouter}')
        ])

        self.cmd('network vrouter list -g {rg}', checks=[
            self.check('@[0].name', '{vrouter}')
        ])

        self.cmd('network vrouter peering create -n {vrouter_peering} --peer-asn 10000 --peer-ip 10.0.0.0 -g {rg} --vrouter-name {vrouter}', checks=[
            self.check('name', '{vrouter_peering}')
        ])

        self.cmd('network vrouter peering update -n {vrouter_peering} --peer-asn 11000 --peer-ip 11.0.0.0 -g {rg} --vrouter-name {vrouter}', checks=[
            self.check('peerAsn', '11000'),
            self.check('peerIp', '11.0.0.0')
        ])

        self.cmd('network vrouter peering show -n {vrouter_peering} -g {rg} --vrouter-name {vrouter}', checks=[
            self.check('name', '{vrouter_peering}')
        ])

        self.cmd('network vrouter peering list -g {rg} --vrouter-name {vrouter}', checks=[
            self.check('@[0].name', '{vrouter_peering}'),
            self.check('length(@)', 1)
        ])

        self.cmd('network vrouter peering delete -n {vrouter_peering} -g {rg} --vrouter-name {vrouter}')

        self.cmd('network vrouter delete -g {rg} -n {vrouter}')

    # @record_only()  # this feature need resource from service team for now.
    @unittest.skip('rg not found')
    @ResourceGroupPreparer(name_prefix='cli_test_virtual_router', location='eastus2euap')
    def test_vrouter_with_virtual_hub_support(self, resource_group, resource_group_location):
        self.kwargs.update({
            'rg': 'test_vrouter_with_virtual_hub_support',    # the subscription needs to be a specified one given by service team
            'location': resource_group_location,
            'vnet': 'vnet2',
            'subnet1': 'subnet1',
            'subnet2': 'subnet2',
            'vrouter': 'vrouter2',
            'peer': 'peer1'
        })

        self.cmd('network vnet create -g {rg} -n {vnet} '
                 '--location {location} '
                 '--subnet-name {subnet1} '
                 '--address-prefix 10.0.0.0/24')

        # a cleanup program runs in short peoridically to assign subnets a NSG within that subscription
        # which will block subnet is assigned to the virtual router
        self.cmd('network vnet subnet update -g {rg} --vnet-name {vnet} -n {subnet1} --remove networkSecurityGroup')
        vnet = self.cmd('network vnet show -g {rg} -n {vnet}').get_output_in_json()

        self.kwargs.update({
            'subnet1_id': vnet['subnets'][0]['id']
        })

        self.cmd('network vrouter create -g {rg} -l {location} -n {vrouter} --hosted-subnet {subnet1_id}', checks=[
            self.check('type', 'Microsoft.Network/virtualHubs'),
            self.check('ipConfigurations', None),
            self.check('provisioningState', 'Succeeded')
        ])

        self.cmd('network vrouter list -g {rg}')

        self.cmd('network vrouter show -g {rg} -n {vrouter}', checks=[
            self.check('virtualRouterAsn', 65515),
            self.check('length(virtualRouterIps)', 2),
        ])

        self.cmd('network vrouter peering create -g {rg} --vrouter-name {vrouter} -n {peer} '
                 '--peer-asn 11000 --peer-ip 10.0.0.120')

        self.cmd('network vrouter peering list -g {rg} --vrouter-name {vrouter}')

        self.cmd('network vrouter peering show -g {rg} --vrouter-name {vrouter} -n {peer}')

        # unable to update unless the ASN's range is required
        # self.cmd('network vrouter peering update -g {rg} --vrouter-name {vrouter} -n {peer} --peer-ip 10.0.0.0')

        self.cmd('network vrouter peering delete -g {rg} --vrouter-name {vrouter} -n {peer}')

        self.cmd('network vrouter delete -g {rg} -n {vrouter}')


class NetworkVirtualHubRouter(ScenarioTest):
    @ResourceGroupPreparer(name_prefix='cli_test_virtual_hub_router', location='centraluseuap')
    def test_network_virtual_hub_router_scenario(self, resource_group, resource_group_location):
        self.kwargs.update({
            'rg': resource_group,
            'location': resource_group_location,
            'vnet': 'vnet2',
            'vhr_ip1': 'vhrip1',
            'subnet1': 'RouteServerSubnet',
            'vrouter': 'vrouter2',
            'peer': 'peer1'
        })

        self.cmd('network vnet create -g {rg} -n {vnet} '
                 '--location {location} '
                 '--subnet-name {subnet1} '
                 '--address-prefix 10.0.0.0/24')

        # a cleanup program runs in short peoridically to assign subnets a NSG within that subscription
        # which will block subnet is assigned to the virtual router
        self.cmd('network vnet subnet update -g {rg} --vnet-name {vnet} -n {subnet1} --remove networkSecurityGroup')
        vnet = self.cmd('network vnet show -g {rg} -n {vnet}').get_output_in_json()
        self.cmd('network public-ip create -g {rg} -n {vhr_ip1} --sku Standard')

        self.kwargs.update({
            'subnet1_id': vnet['subnets'][0]['id']
        })

        self.cmd('network routeserver create -g {rg} -l {location} -n {vrouter} --auto-scale-config min-capacity=3 '
                 '--hosted-subnet {subnet1_id} --public-ip-address {vhr_ip1} --hub-routing-preference aspath',
                 checks=[
                     self.check('type', 'Microsoft.Network/virtualHubs'),
                     self.check('ipConfigurations', None),
                     self.check('provisioningState', 'Succeeded'),
                     self.check("hubRoutingPreference", "ASPath"),
                     self.check('virtualRouterAutoScaleConfiguration.minCapacity', 3)
                 ])

        self.cmd('network routeserver update -g {rg} --name {vrouter}  --allow-b2b-traffic --hub-routing-preference expressroute', checks=[
            self.check('allowBranchToBranchTraffic', True),
            self.check("hubRoutingPreference", "ExpressRoute")
        ])

        self.cmd('network routeserver list -g {rg}')

        self.cmd('network routeserver show -g {rg} -n {vrouter}', checks=[
            self.check('virtualRouterAsn', 65515),
            self.check('length(virtualRouterIps)', 2),
        ])

        self.cmd('network routeserver peering create -g {rg} --routeserver {vrouter} -n {peer} '
                 '--peer-asn 11000 --peer-ip 10.0.0.120')

        self.cmd('network routeserver peering list -g {rg} --routeserver {vrouter}')

        self.cmd('network routeserver peering show -g {rg} --routeserver {vrouter} -n {peer}')

        self.cmd('network routeserver peering list-advertised-routes -g {rg} --routeserver {vrouter} -n {peer}',
                 checks=[self.check("contains(keys(@), 'RouteServiceRole_IN_0')", True)])

        self.cmd('network routeserver peering list-learned-routes -g {rg} --routeserver {vrouter} -n {peer}',
                 checks=[self.check("contains(keys(@), 'RouteServiceRole_IN_1')", True)])

        # unable to update unless the ASN's range is required
        # self.cmd('network routeserver peering update -g {rg} --routeserver {vrouter} -n {peer} --peer-ip 10.0.0.0')

        self.cmd('network routeserver peering delete -g {rg} --routeserver {vrouter} -n {peer} -y')

        self.cmd('network routeserver delete -g {rg} -n {vrouter} -y')


class NetworkSubnetScenarioTests(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_subnet_set_test')
    def test_network_subnet_set(self, resource_group):

        self.kwargs.update({
            'vnet': 'vnet1',
            'vnet_prefix': '123.0.0.0/16',
            'subnet': 'default',
            'subnet_prefix': '123.0.0.0/24',
            'subnet_prefix2': '123.0.5.0/24',
            'nsg': 'test-vnet-nsg'
        })

        self.cmd('network vnet create --resource-group {rg} --name {vnet} --address-prefix {vnet_prefix} --subnet-name {subnet} --subnet-prefix {subnet_prefix}')
        self.cmd('network nsg create --resource-group {rg} --name {nsg}')

        # Test we can update the address space and nsg
        self.cmd('network vnet subnet update --resource-group {rg} --vnet-name {vnet} --name {subnet} --address-prefix {subnet_prefix2} --network-security-group {nsg}', checks=[
            self.check('addressPrefix', '{subnet_prefix2}'),
            self.check('ends_with(@.networkSecurityGroup.id, `/{nsg}`)', True)
        ])

        # test generic update
        self.cmd('network vnet subnet update -g {rg} --vnet-name {vnet} -n {subnet} --set addressPrefix=123.0.0.0/24',
                 checks=self.check('addressPrefix', '123.0.0.0/24'))

        # Test we can get rid of the nsg.
        self.cmd('network vnet subnet update --resource-group {rg} --vnet-name {vnet} --name {subnet} --address-prefix {subnet_prefix2} --network-security-group null',
                 checks=self.check('networkSecurityGroup', None))

        self.cmd('network vnet delete --resource-group {rg} --name {vnet}')
        self.cmd('network nsg delete --resource-group {rg} --name {nsg}')

    @ResourceGroupPreparer(name_prefix='cli_subnet_detach_nat_gateway_', location="eastus2")
    def test_subnet_detach_nat_gateway(self, resource_group, resource_group_location):
        self.kwargs.update({
            'vnet': 'vnet1',
            'vnet_prefix': '123.0.0.0/16',
            'subnet': 'default',
            'subnet_prefix': '123.0.0.0/24',
            'nat': 'test-nat',
            'idle_timeout': 4,
            'sku': "Standard",
            'ip_addr': "pip",
            'ip_prefix': "prefix",
            'idle_timeout_updated': 5,
            'zone': 2,
            'location': resource_group_location,
            'resource_type': 'Microsoft.Network/NatGateways'
        })

        self.cmd('network public-ip create -g {rg} -n {ip_addr} --location {location} --zone {zone} --sku Standard ')
        self.cmd('network public-ip prefix create --length 29 --location {location} --name {ip_prefix} --resource-group {rg} --zone {zone}')
        self.cmd('network nat gateway create --resource-group {rg} --location {location} --public-ip-prefixes {ip_prefix} --name {nat} --public-ip-addresses {ip_addr} --idle-timeout {idle_timeout} --zone {zone}')
        self.cmd('network vnet create --resource-group {rg} --name {vnet} --address-prefix {vnet_prefix}')

        self.cmd('network vnet subnet create --resource-group {rg} --vnet-name {vnet} --name {subnet} --address-prefixes {subnet_prefix} --nat-gateway {nat} --default-outbound false',
                 checks=self.check('ends_with(@.natGateway.id, `/{nat}`)', True))
        self.cmd('network vnet subnet update --resource-group {rg} --vnet-name {vnet} --name {subnet} --nat-gateway null',
                 checks=self.check('natGateway', None))

    @ResourceGroupPreparer(name_prefix='cli_subnet_endpoint_service_test', location="eastus2")
    def test_network_subnet_endpoint_service(self, resource_group):
        self.kwargs.update({
            'vnet': 'vnet1',
            'subnet1': 'subnet1',
            'subnet2': 'subnet2',
            'subnet3': 'subnet3',
            'publicip': 'testip1',
            'publicip2': 'testip2'
        })
        result = self.cmd('network vnet list-endpoint-services -l westus').get_output_in_json()
        self.assertGreaterEqual(len(result), 2)

        public_ip1 = self.cmd('network public-ip create -g {rg} -n {publicip}').get_output_in_json()
        public_ip2 = self.cmd('network public-ip create -g {rg} -n {publicip2}').get_output_in_json()
        self.kwargs.update({
            'public_ip1': public_ip1['publicIp']['id'],
            'public_ip2': public_ip2['publicIp']['id']
        })
        self.cmd('network vnet create -g {rg} -n {vnet}')
        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} -n {subnet1} --address-prefix 10.0.1.0/24 --service-endpoints Microsoft.Storage --default-outbound false',
                 checks=self.check('serviceEndpoints[0].service', 'Microsoft.Storage'))
        self.cmd('network vnet subnet update -g {rg} --vnet-name {vnet} -n {subnet1} --service-endpoints null',
                 checks=self.check('serviceEndpoints', None))

        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} -n {subnet2} --address-prefix 10.0.2.0/24 --endpoints [{{"service":Microsoft.Storage,"network-identifier":{public_ip1}}}] --default-outbound false',
                 checks=[self.check('serviceEndpoints[0].service', 'Microsoft.Storage'),
                         self.check('serviceEndpoints[0].networkIdentifier.id', '{public_ip1}')])
        self.cmd('network vnet subnet update -g {rg} --vnet-name {vnet} -n {subnet2} --service-endpoints null',
                 checks=self.check('serviceEndpoints', None))

        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} -n {subnet3} --address-prefix 10.0.3.0/24 --default-outbound false')
        self.cmd('network vnet subnet update -g {rg} --vnet-name {vnet} -n {subnet3} --endpoints [{{"service":Microsoft.Storage,"network-identifier":{public_ip2}}}]',
                 checks=[self.check('serviceEndpoints[0].service', 'Microsoft.Storage'),
                         self.check('serviceEndpoints[0].networkIdentifier.id', '{public_ip2}')])

    @ResourceGroupPreparer(name_prefix='cli_subnet_delegation')
    def test_network_subnet_delegation(self, resource_group):
        self.kwargs.update({
            'vnet': 'vnet1',
            'subnet': 'subnet1',
        })
        result = self.cmd('network vnet subnet list-available-delegations -l westcentralus').get_output_in_json()
        self.assertTrue(len(result) > 1, True)
        result = self.cmd('network vnet subnet list-available-delegations -g {rg}').get_output_in_json()
        self.assertTrue(len(result) > 1, True)

        self.cmd('network vnet create -g {rg} -n {vnet} -l westcentralus')
        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} -n {subnet} --address-prefix 10.0.0.0/24 --delegations Microsoft.Web.serverFarms --default-outbound false', checks=[
            self.check('delegations[0].serviceName', 'Microsoft.Web/serverFarms')
        ])
        # verify the update command, and that CLI validation will accept either serviceName or Name
        self.cmd('network vnet subnet update -g {rg} --vnet-name {vnet} -n {subnet} --delegations Microsoft.Sql/managedInstances',
                 checks=self.check('delegations[0].serviceName', 'Microsoft.Sql/managedInstances'))

    @ResourceGroupPreparer(name_prefix='test_subnet_with_private_endpoint_option')
    def test_subnet_with_private_endpoint_and_private_link_options(self, resource_group):
        self.kwargs.update({
            'vnet': 'MyVnet',
            'subnet1': 'MySubnet1',
            'subnet2': 'MySubnet2',
            'subnet3': 'MySubnet3',
        })

        self.cmd('network vnet create -g {rg} -n {vnet}')

        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} '
                 '--address-prefixes 10.0.1.0/24 '
                 '--name {subnet1} '
                 '--disable-private-endpoint-network-policies true '
                 '--default-outbound false', checks=[
                     self.check('addressPrefix', '10.0.1.0/24'),
                     self.check('privateEndpointNetworkPolicies', 'Disabled'),
                     self.check('privateLinkServiceNetworkPolicies', 'Enabled')
                 ])

        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} '
                 '--address-prefixes 10.0.2.0/24 '
                 '--name {subnet2} '
                 '--disable-private-link-service-network-policies true '
                 '--default-outbound false', checks=[
                     self.check('addressPrefix', '10.0.2.0/24'),
                     self.check('privateEndpointNetworkPolicies', 'Disabled'),
                     self.check('privateLinkServiceNetworkPolicies', 'Disabled')
                 ])

        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} '
                 '--address-prefixes 10.0.3.0/24 '
                 '--name {subnet3} '
                 '--disable-private-endpoint-network-policies true '
                 '--disable-private-link-service-network-policies true '
                 '--default-outbound false', checks=[
                     self.check('addressPrefix', '10.0.3.0/24'),
                     self.check('privateEndpointNetworkPolicies', 'Disabled'),
                     self.check('privateLinkServiceNetworkPolicies', 'Disabled')
                 ])

    @ResourceGroupPreparer(name_prefix='cli_subnet_default_outbound_access')
    def test_network_subnet_default_outbound_access(self, resource_group):
        self.kwargs.update({
            'vnet': 'vnet1',
            'subnet1': 'subnet1',
            'subnet2': 'subnet2',
        })
        self.cmd('network vnet create -g {rg} -n {vnet} -l westcentralus')
        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} -n {subnet1} --address-prefixes 10.0.3.0/24 --default-outbound-access false',
                 self.check('defaultOutboundAccess', False))
        self.cmd('network vnet subnet update -g {rg} --vnet-name {vnet} -n {subnet1} --default-outbound-access true',
                 self.check('defaultOutboundAccess', True))

        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} -n {subnet2} --address-prefixes 10.0.4.0/24 --default-outbound-access true',
                 self.check('defaultOutboundAccess', True))
        self.cmd('network vnet subnet update -g {rg} --vnet-name {vnet} -n {subnet2} --default-outbound-access false',
                 self.check('defaultOutboundAccess', False))

        self.cmd('network vnet subnet show -g {rg} --vnet-name {vnet} -n {subnet2}',
                 self.check('defaultOutboundAccess', False))

    @ResourceGroupPreparer(name_prefix='cli_subnet_with_sharing_scope', location='westcentralus')
    def test_network_subnet_with_sharing_scope(self, resource_group):
        self.kwargs.update({
            'vnet': 'vnet1',
            'subnet': 'subnet1'
        })
        self.cmd('az network vnet create -g {rg} -n {vnet} -l westcentralus --address-prefixes 10.0.0.0/16')
        self.cmd('az network vnet subnet create -g {rg} --vnet-name {vnet} -n {subnet} --address-prefixes 10.0.0.0/16 --default-outbound false --sharing-scope Tenant')
        self.cmd('network vnet subnet show -g {rg} --vnet-name {vnet} -n {subnet}',
                 checks=self.check('sharingScope', 'Tenant'))


class NetworkActiveActiveCrossPremiseScenarioTest(ScenarioTest):  # pylint: disable=too-many-instance-attributes

    @ResourceGroupPreparer(name_prefix='cli_test_active_active_cross_premise_connection', location='westus2')
    def test_network_active_active_cross_premise_connection(self, resource_group):
        self.kwargs.update({
            'vnet1': 'vnet1',
            'vnet_prefix1': '10.11.0.0/16',
            'vnet_prefix2': '10.12.0.0/16',
            'vnet1_asn': 65010,
            'gw_subnet': 'GatewaySubnet',
            'gw_subnet_prefix': '10.12.255.0/27',
            'gw_ip1': 'gwip1',
            'gw_ip2': 'gwip2',
            'gw1': 'gw1',
            'lgw2': 'lgw2',
            'lgw_ip': '131.107.72.22',
            'lgw_prefix': '10.52.255.253/32',
            'bgp_peer1': '10.52.255.253',
            'lgw_asn': 65050,
            'lgw_loc': 'eastus',
            'conn_151': 'Vnet1toSite5_1',
            'conn_152': 'Vnet1toSite5_2',
            'shared_key': 'abc123',
            'shared_key2': 'a1b2c3',
            'lgw3': 'lgw3',
            'lgw3_ip': '131.107.72.23',
            'lgw3_prefix': '10.52.255.254/32',
            'bgp_peer2': '10.52.255.254'
        })

        self.cmd('network vnet create -g {rg} -n {vnet1} --address-prefix {vnet_prefix1} {vnet_prefix2} --subnet-name {gw_subnet} --subnet-prefix {gw_subnet_prefix}')

        self.cmd('network public-ip create -g {rg} -n {gw_ip1} --sku Standard --zone 1 2 3')
        self.cmd('network public-ip create -g {rg} -n {gw_ip2} --sku Standard --zone 1 2 3')

        self.cmd('network vnet-gateway create -g {rg} -n {gw1} --vnet {vnet1} --sku VpnGw1AZ --asn {vnet1_asn} --public-ip-addresses {gw_ip1} {gw_ip2} --tags foo=doo')
        self.cmd('network vnet-gateway wait -g {rg} -n {gw1} --created')

        import time
        time.sleep(3 * 60)  # 3min

        self.cmd('network vnet-gateway update -g {rg} -n {gw1} --tags foo=boo --no-wait')
        self.cmd('network vnet-gateway wait -g {rg} -n {gw1} --updated')

        self.cmd('network local-gateway create -g {rg} -n {lgw2} -l {lgw_loc} --gateway-ip-address {lgw_ip} --local-address-prefixes {lgw_prefix} --asn {lgw_asn} --bgp-peering-address {bgp_peer1}')
        self.cmd('network vpn-connection create -g {rg} -n {conn_151} --vnet-gateway1 {gw1} --local-gateway2 {lgw2} --shared-key {shared_key} --enable-bgp')
        self.cmd('network vpn-connection shared-key reset -g {rg} --connection-name {conn_151} --key-length 128')
        sk1 = self.cmd(
            'network vpn-connection shared-key show -g {rg} --connection-name {conn_151}').get_output_in_json()
        self.cmd('network vpn-connection shared-key update -g {rg} --connection-name {conn_151} --value {shared_key2}')
        sk2 = self.cmd('network vpn-connection shared-key show -g {rg} --connection-name {conn_151}',
                       checks=self.check('value', '{shared_key2}')).get_output_in_json()

        self.assertNotEqual(sk1, sk2)

        self.cmd('network local-gateway create -g {rg} -n {lgw3} -l {lgw_loc} --gateway-ip-address {lgw3_ip} --local-address-prefixes {lgw3_prefix} --asn {lgw_asn} --bgp-peering-address {bgp_peer2}')
        self.cmd('network vpn-connection create -g {rg} -n {conn_152} --vnet-gateway1 {gw1} --local-gateway2 {lgw3} --shared-key {shared_key} --enable-bgp')

class NetworkActiveActiveVnetScenarioTest(ScenarioTest):  # pylint: disable=too-many-instance-attributes

    def __init__(self, method_name):
        self.sas_replacer = StorageAccountSASReplacer()
        super().__init__(method_name, recording_processors=[
            self.sas_replacer
        ])

    @AllowLargeResponse()
    @ResourceGroupPreparer(name_prefix='cli_test_active_active_vnet_vnet_connection')
    @StorageAccountPreparer(name_prefix='clitestvpncnn')
    def test_network_active_active_vnet_connection(self, resource_group, storage_account):
        from datetime import datetime, timedelta
        self.kwargs.update({
            'subnet': 'GatewaySubnet',
            'vnet1': 'vnet1',
            'vnet1_prefix': '10.21.0.0/16',
            'vnet1_asn': 65010,
            'gw1': 'vgw1',
            'gw1_prefix': '10.21.255.0/27',
            'gw1_ip1': 'gw1ip1',
            'gw1_ip2': 'gw1ip2',
            'vnet2': 'vnet2',
            'vnet2_prefix': '10.22.0.0/16',
            'vnet2_asn': 65020,
            'gw2': 'vgw2',
            'gw2_prefix': '10.22.255.0/27',
            'gw2_ip1': 'gw2ip1',
            'gw2_ip2': 'gw2ip2',
            'key': 'abc123',
            'conn12': 'vnet1to2',
            'conn21': 'vnet2to1',
            'bgp_peer1': '10.52.255.253',
            'bgp_peer2': '10.53.255.253',
            'storage_account': storage_account,
            'ctn': self.create_random_name(prefix='clitestvpngw', length=24),
            'expiry': (datetime.utcnow() + timedelta(hours=3)).strftime('%Y-%m-%dT%H:%MZ')
        })

        self.cmd('storage container create --account-name {storage_account} --name {ctn}')
        sas = self.cmd(
            'storage blob generate-sas -n src --account-name {storage_account} -c {ctn} --permissions acrwd --expiry {expiry} -otsv').output.strip()
        self.kwargs['sas_url'] = 'https://{}.blob.azure.com/{}?{}'.format(self.kwargs['storage_account'],
                                                                          self.kwargs['ctn'], sas)
        self.sas_replacer.add_sas_token(sas)

        # Create one VNet with two public IPs
        self.cmd('network vnet create -g {rg} -n {vnet1} --address-prefix {vnet1_prefix} --subnet-name {subnet} --subnet-prefix {gw1_prefix}')
        self.cmd('network public-ip create -g {rg} -n {gw1_ip1}')
        self.cmd('network public-ip create -g {rg} -n {gw1_ip2}')

        # Create second VNet with two public IPs
        self.cmd('network vnet create -g {rg} -n {vnet2} --address-prefix {vnet2_prefix} --subnet-name {subnet} --subnet-prefix {gw2_prefix}')
        self.cmd('network public-ip create -g {rg} -n {gw2_ip1}')
        self.cmd('network public-ip create -g {rg} -n {gw2_ip2}')

        self.cmd('network vnet-gateway create -g {rg} -n {gw1} --vnet {vnet1} --sku VpnGw1 --asn {vnet1_asn} --public-ip-addresses {gw1_ip1} {gw1_ip2} --bgp-peering-address {bgp_peer1} --no-wait')
        self.cmd('network vnet-gateway create -g {rg} -n {gw2} --vnet {vnet2} --sku VpnGw1 --asn {vnet2_asn} --public-ip-addresses {gw2_ip1} {gw2_ip2} --bgp-peering-address {bgp_peer2} --no-wait')

        # wait for gateway completion to finish
        self.cmd('network vnet-gateway wait -g {rg} -n {gw1} --created')
        self.cmd('network vnet-gateway wait -g {rg} -n {gw2} --created')

        # create and connect the VNet gateways
        self.cmd('network vpn-connection create -g {rg} -n {conn12} --vnet-gateway1 {gw1} --vnet-gateway2 {gw2} --shared-key {key} --enable-bgp')
        self.cmd('network vpn-connection create -g {rg} -n {conn21} --vnet-gateway1 {gw2} --vnet-gateway2 {gw1} --shared-key {key} --enable-bgp')
        self.cmd('network vpn-connection list-ike-sas -g {rg} -n {conn12}')
        output = self.cmd('network vpn-connection packet-capture start -g {rg} -n {conn12}').output.strip()
        self.assertTrue('Successful' in output, 'Expected Successful in output.\nActual: {}'.format(output))
        # currently we cannot create traffic by cli command. So it will return an error when stop.
        with self.assertRaisesRegex(HttpResponseError, 'The response did not contain any data'):
            self.cmd('network vpn-connection packet-capture stop -g {rg} -n {conn12} --sas-url {sas_url}')


class NetworkVpnGatewayScenarioTest(ScenarioTest):

    def __init__(self, method_name):
        self.sas_replacer = StorageAccountSASReplacer()
        super().__init__(method_name, recording_processors=[
            self.sas_replacer
        ])

    @ResourceGroupPreparer(name_prefix='cli_test_vpn_gateway')
    def test_network_vpn_gateway(self, resource_group):

        self.kwargs.update({
            'vnet1': 'myvnet1',
            'vnet2': 'myvnet2',
            'vnet3': 'myvnet3',
            'gw1': 'gateway1',
            'gw2': 'gateway2',
            'gw3': 'gateway3',
            'ip1': 'pubip1',
            'ip2': 'pubip2',
            'ip3': 'pubip3',
            'custom_routes1': "101.168.0.6/32",
            'custom_routes2': "102.168.0.6/32"
        })

        self.cmd('network public-ip create -n {ip1} -g {rg}')
        self.cmd('network public-ip create -n {ip2} -g {rg}')
        self.cmd('network public-ip create -n {ip3} -g {rg}')
        self.cmd('network vnet create -g {rg} -n {vnet1} --subnet-name GatewaySubnet --address-prefix 10.0.0.0/16 --subnet-prefix 10.0.0.0/24')
        self.cmd('network vnet create -g {rg} -n {vnet2} --subnet-name GatewaySubnet --address-prefix 10.1.0.0/16')
        self.cmd('network vnet create -g {rg} -n {vnet3} --subnet-name GatewaySubnet --address-prefix 10.2.0.0/16')

        self.kwargs.update({'sub': self.get_subscription_id()})
        self.kwargs.update({
            'vnet1_id': '/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNetworks/{vnet1}'.format(**self.kwargs),
            'vnet2_id': '/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNetworks/{vnet2}'.format(**self.kwargs)
        })

        with self.assertRaisesRegex(HttpResponseError, 'InvalidGatewaySkuSpecifiedForGatewayDeploymentType'):
            self.cmd(
                'network vnet-gateway create -g {rg} -n {gw1} --vnet {vnet1_id} --public-ip-address {ip1} --gateway-type ExpressRoute --vpn-gateway-generation Generation1')

        self.cmd('network vnet-gateway create -g {rg} -n {gw1} --vnet {vnet1_id} --public-ip-address {ip1} --vpn-gateway-generation Generation1 --custom-routes {custom_routes1} --sku VpnGw1 --no-wait')
        self.cmd('network vnet-gateway create -g {rg} -n {gw2} --vnet {vnet2_id} --public-ip-address {ip2} --sku VpnGw1 --no-wait')
        self.cmd('network vnet-gateway create -g {rg} -n {gw3} --vnet {vnet3} --public-ip-address {ip3} --no-wait --sku VpnGw1 --asn 12345 --bgp-peering-address 10.2.250.250 --peer-weight 50')

        self.cmd('network vnet-gateway wait -g {rg} -n {gw1} --created')
        self.cmd('network vnet-gateway wait -g {rg} -n {gw2} --created')
        self.cmd('network vnet-gateway wait -g {rg} -n {gw3} --created')

        self.cmd('network vnet-gateway show -g {rg} -n {gw1}', checks=[
            self.check('gatewayType', 'Vpn'),
            self.check('sku.capacity', 2),
            self.check('sku.name', 'VpnGw1'),
            self.check('vpnType', 'RouteBased'),
            self.check('vpnGatewayGeneration', 'Generation1'),
            self.check('enableBgp', False),
            self.check('customRoutes.addressPrefixes[0]', self.kwargs['custom_routes1'])
        ])

        self.cmd('network vnet-gateway update -g {rg} -n {gw1} --custom-routes {custom_routes1} {custom_routes2}', checks=[
            self.check('length(customRoutes.addressPrefixes)', 2)
        ])

        self.cmd('network vnet-gateway show -g {rg} -n {gw2}', checks=[
            self.check('gatewayType', 'Vpn'),
            self.check('sku.capacity', 2),
            self.check('sku.name', 'VpnGw1'),
            self.check('vpnType', 'RouteBased'),
            self.check('enableBgp', False)
        ])
        self.cmd('network vnet-gateway show -g {rg} -n {gw3}', checks=[
            self.check('sku.name', 'VpnGw1'),
            self.check('enableBgp', True),
            self.check('bgpSettings.asn', 12345),
            self.check('bgpSettings.bgpPeeringAddress', '10.2.250.250'),
            self.check('bgpSettings.peerWeight', 50),
            self.check('enableHighBandwidthVpnGateway', False)
        ])

        self.kwargs.update({
            'conn12': 'conn1to2',
            'conn21': 'conn2to1',
            'gw1_id': '/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNetworkGateways/{gw1}'.format(**self.kwargs)
        })

        self.cmd('network vpn-connection create -n {conn12} -g {rg} --shared-key 123 --vnet-gateway1 {gw1_id} --vnet-gateway2 {gw2} --tags foo=doo')
        self.cmd('network vpn-connection update -n {conn12} -g {rg} --routing-weight 25 --tags foo=boo',
                 checks=self.check('routingWeight', 25))
        self.cmd('network vpn-connection create -n {conn21} -g {rg} --shared-key 123 --vnet-gateway2 {gw1_id} --vnet-gateway1 {gw2}')

        self.cmd('network vnet-gateway list-learned-routes -g {rg} -n {gw1}')
        self.cmd('network vnet-gateway list-advertised-routes -g {rg} -n {gw1} --peer 10.1.1.1')
        self.cmd('network vnet-gateway list-bgp-peer-status -g {rg} -n {gw1} --peer 10.1.1.1')
        self.cmd('network vpn-connection list -g {rg} --vnet-gateway {gw1}', checks=[
            self.check('length(@)', 1)
        ])

    @ResourceGroupPreparer(name_prefix='cli_test_vpn_gateway_sku_', location='westus3')
    def test_network_vpn_gateway_sku(self, resource_group):
        self.kwargs.update({
            'vnet1': 'myvnet1',
            'gw1': 'gateway1',
            'ip1': 'pubip1',
            'custom_routes1': "101.168.0.6/32",
            'custom_routes2': "102.168.0.6/32"
        })

        self.cmd('network public-ip create -n {ip1} -g {rg}')
        self.cmd('network vnet create -g {rg} -n {vnet1} --subnet-name GatewaySubnet --address-prefix 10.0.0.0/16 --subnet-prefix 10.0.0.0/24')

        self.cmd(
            "network vnet-gateway create -n {gw1} -g {rg} --public-ip-address {ip1} --vnet {vnet1} --gateway-type ExpressRoute --resiliency-model SingleHomed --sku ErGwScale --min-scale-unit 3 --max-scale-unit 5",
            checks=[
                self.check("vnetGateway.autoScaleConfiguration.bounds.max", 5),
                self.check("vnetGateway.autoScaleConfiguration.bounds.min", 3),
                self.check("vnetGateway.resiliencyModel", "SingleHomed"),
            ]
        )
        self.cmd(
            "network vnet-gateway update -n {gw1} -g {rg} --min-scale-unit 4 --max-scale-unit 8",
            checks=[
                self.check("autoScaleConfiguration.bounds.max", 8),
                self.check("autoScaleConfiguration.bounds.min", 4),
            ]
        )

    @ResourceGroupPreparer(name_prefix='cli_test_vpn_gateway_aad_')
    def test_network_vpn_gateway_aad(self, resource_group):
        self.kwargs.update({
            'vnet': 'vnet',
            'gw': 'gw',
            'ip': 'ip',
            'aad_tenant': 'https://login.microsoftonline.com/0ab2c4f4-81e6-44cc-a0b2-b3a47a1443f4',
            'aad_issuer': 'https://sts.windows.net/0ab2c4f4-81e6-44cc-a0b2-b3a47a1443f4/',
            'aad_audience': 'a21fce82-76af-45e6-8583-a08cb3b956f9'
        })

        self.cmd('network public-ip create -g {rg} -n {ip} ')
        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name GatewaySubnet')
        self.cmd('network vnet-gateway create -g {rg} -n {gw} '
                 '--vnet {vnet} --public-ip-address {ip} '
                 '--gateway-type Vpn --vpn-type RouteBased '
                 '--sku VpnGw1 '
                 '--client-protocol OpenVPN '
                 '--address-prefixes 201.169.0.0/16 ')
        self.cmd('network vnet-gateway show -g {rg} -n {gw}', checks=[
            self.check('sku.name', 'VpnGw1'),
            self.check('enableBgp', False),
            self.check('vpnType', 'RouteBased'),
            self.check('vpnClientConfiguration.vpnClientProtocols[0]', "OpenVPN")
        ])

        self.cmd('network vnet-gateway aad assign -g {rg} --gateway-name {gw} '
                 '--tenant {aad_tenant} '
                 '--audience {aad_audience} '
                 '--issuer {aad_issuer} ')
        self.cmd('network vnet-gateway show -g {rg} -n {gw}', checks=[
            self.check('vpnClientConfiguration.aadTenant', self.kwargs['aad_tenant']),
            self.check('vpnClientConfiguration.aadIssuer', self.kwargs['aad_issuer']),
            self.check('vpnClientConfiguration.aadAudience', self.kwargs['aad_audience'])
        ])
        self.cmd('network vnet-gateway aad show -g {rg} --gateway-name {gw}', checks=[
            self.check('aadTenant', self.kwargs['aad_tenant'])
        ])

        self.cmd('network vnet-gateway aad remove -g {rg} --gateway-name {gw}').get_output_in_json()
        self.cmd('network vnet-gateway aad show -g {rg} --gateway-name {gw}', checks=[
            self.check('aadTenant', None),
            self.check('aadIssuer', None),
            self.check('aadAudience', None)
        ])

    @ResourceGroupPreparer(name_prefix='cli_test_vpn_gateway_disconnect_connects_')
    def test_network_vpn_gateway_disconnect_connects(self, resource_group):
        self.kwargs.update({
            'vnet1': 'myvnet1',
            'vnet2': 'myvnet2',
            'gw1': 'gateway1',
            'gw2': 'gateway2',
            'ip1': 'pubip1',
            'ip2': 'pubip2',
        })

        self.cmd('network public-ip create -n {ip1} -g {rg}')
        self.cmd('network public-ip create -n {ip2} -g {rg}')
        self.cmd('network vnet create -g {rg} -n {vnet1} --subnet-name GatewaySubnet --address-prefix 10.0.0.0/16')
        self.cmd('network vnet create -g {rg} -n {vnet2} --subnet-name GatewaySubnet --address-prefix 10.1.0.0/16')

        self.cmd('network vnet-gateway create -g {rg} -n {gw1} --vnet {vnet1} --public-ip-address {ip1} '
                 '--sku VpnGw1 --gateway-type Vpn --vpn-type RouteBased '
                 '--vpn-gateway-generation Generation1 '
                 '--address-prefixes 172.16.0.0/24 --client-protocol IkeV2 '
                 '--no-wait')
        self.cmd('network vnet-gateway create -g {rg} -n {gw2} --vnet {vnet2} --public-ip-address {ip2} '
                 '--sku VpnGw1 --gateway-type Vpn --vpn-type RouteBased '
                 '--vpn-gateway-generation Generation1 --no-wait')

        self.cmd('network vnet-gateway wait -g {rg} -n {gw1} --created')
        self.cmd('network vnet-gateway wait -g {rg} -n {gw2} --created')

        self.kwargs.update({
            'conn12': 'conn1to2',
            'conn21': 'conn2to1',
        })

        self.cmd('network vpn-connection create -n {conn12} -g {rg} --shared-key 123 '
                 '--vnet-gateway1 {gw1} --vnet-gateway2 {gw2}')
        self.cmd('network vpn-connection create -n {conn21} -g {rg} --shared-key 123 '
                 '--vnet-gateway2 {gw1} --vnet-gateway1 {gw2}')
        self.cmd('network vnet-gateway disconnect-vpn-connections -g {rg} -n {gw1} --vpn-connections {conn12}')

    @AllowLargeResponse()
    @ResourceGroupPreparer(name_prefix='cli_test_vpn_gateway_package_capture', location='westus')
    @StorageAccountPreparer(name_prefix='clitestvpngw')
    def test_network_vpn_gateway_package_capture(self, resource_group, storage_account):
        from datetime import datetime, timedelta
        self.kwargs.update({
            'vnet1': 'myvnet1',
            'gw1': 'gateway1',
            'gw1_sku': 'VpnGw1',
            'ip1': 'pubip1',
            'storage_account': storage_account,
            'ctn': self.create_random_name(prefix='clitestvpngw', length=24),
            'expiry': (datetime.utcnow() + timedelta(hours=3)).strftime('%Y-%m-%dT%H:%MZ')
        })

        self.cmd('storage container create --account-name {storage_account} --name {ctn}')
        sas = self.cmd(
            'storage blob generate-sas -n src --account-name {storage_account} -c {ctn} --permissions acrwd --expiry {expiry} -otsv').output.strip()
        self.kwargs['sas_url'] = 'https://{}.blob.azure.com/{}?{}'.format(self.kwargs['storage_account'],
                                                                          self.kwargs['ctn'], sas)
        self.sas_replacer.add_sas_token(sas)

        self.cmd('network public-ip create -n {ip1} -g {rg}')
        self.cmd('network vnet create -g {rg} -n {vnet1} --subnet-name GatewaySubnet --address-prefix 10.0.0.0/16 --subnet-prefix 10.0.0.0/24')
        self.cmd('network vnet-gateway create -g {rg} -n {gw1} --vnet {vnet1} --public-ip-address {ip1} --sku {gw1_sku}')
        output = self.cmd('network vnet-gateway packet-capture start -g {rg} -n {gw1}').output.strip()
        self.assertTrue('Successful' in output, 'Expected Successful in output.\nActual: {}'.format(output))
        # currently we cannot create traffic by cli command. So it will return an error when stop.
        with self.assertRaisesRegex(HttpResponseError, 'The response did not contain any data'):
            self.cmd('network vnet-gateway packet-capture stop -g {rg} -n {gw1} --sas-url {sas_url}')


class NetworkVpnClientPackageScenarioTest(ScenarioTest):

    @staticmethod
    def _generate_p2s_root_cert_public_file(cert_path, common_name="VpnGatewayAuthCert"):
        """
        Generate a self-signed Root CA public certificate file for P2S root-cert upload.
        The file content is PEM (BEGIN/END CERTIFICATE), which is acceptable for public cert data.
        """
        try:
            from cryptography import x509
            from cryptography.x509.oid import NameOID
            from cryptography.hazmat.primitives import hashes, serialization
            from cryptography.hazmat.primitives.asymmetric import rsa
            from cryptography.hazmat.backends import default_backend
            import datetime

            # timezone-aware now
            try:
                from datetime import timezone
                now = datetime.datetime.now(timezone.utc)
            except ImportError:
                now = datetime.datetime.utcnow()

            # Root key (private key not exported; we only write public cert)
            root_key = rsa.generate_private_key(
                public_exponent=65537,
                key_size=2048,
                backend=default_backend()
            )

            subject = x509.Name([
                x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
                x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Washington"),
                x509.NameAttribute(NameOID.LOCALITY_NAME, u"Redmond"),
                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Test Organization"),
                x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"IT"),
                x509.NameAttribute(NameOID.COMMON_NAME, common_name),
            ])

            cert = x509.CertificateBuilder().subject_name(
                subject
            ).issuer_name(
                subject  # self-signed root
            ).public_key(
                root_key.public_key()
            ).serial_number(
                x509.random_serial_number()
            ).not_valid_before(
                now - datetime.timedelta(minutes=5)
            ).not_valid_after(
                now + datetime.timedelta(days=3650)
            ).add_extension(
                x509.BasicConstraints(ca=True, path_length=1),
                critical=True,
            ).add_extension(
                x509.KeyUsage(
                    digital_signature=True,
                    key_cert_sign=True,
                    crl_sign=True,
                    key_encipherment=False,
                    content_commitment=False,
                    data_encipherment=False,
                    key_agreement=False,
                    encipher_only=False,
                    decipher_only=False,
                ),
                critical=True,
            ).add_extension(
                x509.SubjectKeyIdentifier.from_public_key(root_key.public_key()),
                critical=False,
            ).sign(root_key, hashes.SHA256(), default_backend())

            os.makedirs(os.path.dirname(cert_path), exist_ok=True)
            with open(cert_path, "wb") as f:
                # write public cert as PEM (public only)
                f.write(cert.public_bytes(serialization.Encoding.PEM))

        except ImportError as e:
            raise Exception("cryptography package is required for certificate generation. ")

    @ResourceGroupPreparer('cli_test_vpn_client_package')
    def test_vpn_client_package(self, resource_group):
        import tempfile
        import shutil

        # create a temporary folder for generated public root cert
        temp_dir = tempfile.mkdtemp()
        cert_path = os.path.join(temp_dir, 'VpnGatewayAuthCert.cer')

        try:
            # generate a root cert public file dynamically (avoid static cert dependency)
            self._generate_p2s_root_cert_public_file(cert_path)

            self.kwargs.update({
                'vnet': 'vnet1',
                'public_ip': 'pip1',
                'gateway_prefix': '100.1.1.0/24',
                'gateway': 'vgw1',
                'gw_sku': 'VpnGw1AZ',
                'cert': 'cert1',
                'cert_path': cert_path,
            })

            self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name GatewaySubnet')
            self.cmd('network public-ip create -g {rg} -n {public_ip}')
            self.cmd('network vnet-gateway create -g {rg} -n {gateway} --address-prefix {gateway_prefix} --vnet {vnet} --public-ip-address {public_ip} --sku {gw_sku}')
            self.cmd('network vnet-gateway root-cert create -g {rg} --gateway-name {gateway} -n {cert} --public-cert-data "{cert_path}"')

            # test vnet-gateway revoked-cert create
            self.cmd('network vnet-gateway revoked-cert create -g {rg} -n MyCer --gateway-name {gateway} --thumbprint e806da0b7fe24f47e76fa269dc4ed76dac4b39d0')

            # test vnet-gateway revoked-cert delete
            self.cmd('network vnet-gateway revoked-cert delete -g {rg} -n MyCer --gateway-name {gateway}')

            output = self.cmd('network vnet-gateway vpn-client generate -g {rg} -n {gateway}').get_output_in_json()
            self.assertTrue('.zip' in output, 'Expected ZIP file in output.\nActual: {}'.format(str(output)))

            output = self.cmd('network vnet-gateway vpn-client show-url -g {rg} -n {gateway}').get_output_in_json()
            self.assertTrue('.zip' in output, 'Expected ZIP file in output.\nActual: {}'.format(str(output)))

            self.cmd('network vnet-gateway vpn-client ipsec-policy set -g {rg} -n {gateway} --ike-encryption AES256 --ike-integrity SHA384 --dh-group DHGroup24 --ipsec-encryption GCMAES256 --ipsec-integrity GCMAES256 --pfs-group PFS24 --sa-lifetime 7200 --sa-max-size 2048')
            self.cmd('network vnet-gateway vpn-client ipsec-policy show -g {rg} -n {gateway}', checks=[
                self.check('dhGroup', 'DHGroup24'),
                self.check('ikeEncryption', 'AES256'),
                self.check('ikeIntegrity', 'SHA384'),
                self.check('ipsecEncryption', 'GCMAES256'),
                self.check('ipsecIntegrity', 'GCMAES256'),
                self.check('pfsGroup', 'PFS24'),
                self.check('saDataSizeKilobytes', 2048),
                self.check('saLifeTimeSeconds', 7200),
            ])

        finally:
            if os.path.exists(temp_dir):
                shutil.rmtree(temp_dir)


class NetworkTrafficManagerScenarioTest(ScenarioTest):

    @ResourceGroupPreparer('cli_test_traffic_manager')
    def test_network_traffic_manager(self, resource_group):

        self.kwargs.update({
            'tm': 'mytmprofile',
            'endpoint': 'myendpoint',
            'dns': 'mytrafficmanager001100a'
        })

        self.cmd('network traffic-manager profile check-dns -n myfoobar1')
        self.cmd('network traffic-manager profile create -n {tm} -g {rg} --routing-method priority --unique-dns-name {dns} --tags foo=doo',
                 checks=self.check('TrafficManagerProfile.trafficRoutingMethod', 'Priority'))
        self.cmd('network traffic-manager profile show -g {rg} -n {tm}',
                 checks=self.check('dnsConfig.relativeName', '{dns}'))
        self.cmd('network traffic-manager profile update -n {tm} -g {rg} --routing-method weighted --tags foo=boo',
                 checks=self.check('trafficRoutingMethod', 'Weighted'))
        self.cmd('network traffic-manager profile list -g {rg}')

        # Endpoint tests
        self.cmd('network traffic-manager endpoint create -n {endpoint} --profile-name {tm} -g {rg} --type externalEndpoints --weight 50 --target www.microsoft.com',
                 checks=self.check('type', 'Microsoft.Network/trafficManagerProfiles/externalEndpoints'))
        self.cmd('network traffic-manager endpoint update -n {endpoint} --profile-name {tm} -g {rg} --type externalEndpoints --weight 25 --target www.contoso.com', checks=[
            self.check('weight', 25),
            self.check('target', 'www.contoso.com')
        ])
        self.cmd('network traffic-manager endpoint show -g {rg} --profile-name {tm} -t externalEndpoints -n {endpoint}')
        self.cmd('network traffic-manager endpoint list -g {rg} --profile-name {tm} -t externalEndpoints',
                 checks=self.check('length(@)', 1))

        # test show-geographic-hierarchy
        self.cmd('network traffic-manager endpoint show-geographic-hierarchy', checks=[
            self.check('type', 'Microsoft.Network/trafficManagerGeographicHierarchies')
        ])

        # ensure a profile with endpoints can be updated
        self.cmd('network traffic-manager profile update -n {tm} -g {rg}')

        self.cmd('network traffic-manager endpoint delete -g {rg} --profile-name {tm} -t externalEndpoints -n {endpoint}')
        self.cmd('network traffic-manager endpoint list -g {rg} --profile-name {tm} -t externalEndpoints',
                 checks=self.check('length(@)', 0))

        self.cmd('network traffic-manager profile delete -g {rg} -n {tm}')

    @ResourceGroupPreparer('cli_test_traffic_manager2')
    def test_network_traffic_manager2(self, resource_group):
        self.kwargs.update({
            'tm': 'mytmprofile2',
            'dns': 'mytrafficmanager001100a2'
        })
        self.cmd('network traffic-manager profile create -n {tm} -g {rg} --routing-method Multivalue --unique-dns-name {dns} --max-return 3 --tags foo=doo',
                 checks=self.check('TrafficManagerProfile.trafficRoutingMethod', 'MultiValue'))

        self.cmd('network traffic-manager profile update -n {tm} -g {rg} --routing-method MultiValue  --max-return 4 --tags foo=boo',
                 checks=self.check('maxReturn', 4))

    @ResourceGroupPreparer('cli_test_traffic_manager_subnet')
    def test_network_traffic_manager_subnet_routing(self, resource_group):

        self.kwargs.update({
            'tm': 'tm1',
            'endpoint': 'ep1',
            'dns': self.create_random_name('testtm', 20),
            'pip': 'ip1',
            'ip_dns': self.create_random_name('testpip', 20)
        })

        self.cmd('network traffic-manager profile create -n {tm} -g {rg} --routing-method subnet --unique-dns-name {dns} --custom-headers foo=bar --status-code-ranges 200-202', checks=[
            self.check('TrafficManagerProfile.monitorConfig.expectedStatusCodeRanges[0].min', 200),
            self.check('TrafficManagerProfile.monitorConfig.expectedStatusCodeRanges[0].max', 202),
            self.check('TrafficManagerProfile.monitorConfig.customHeaders[0].name', 'foo'),
            self.check('TrafficManagerProfile.monitorConfig.customHeaders[0].value', 'bar')
        ])
        self.kwargs['ip_id'] = self.cmd('network public-ip create -g {rg} -n {pip} --dns-name {ip_dns} --query publicIp.id').get_output_in_json()
        self.cmd('network traffic-manager profile update -n {tm} -g {rg} --status-code-ranges 200-204 --custom-headers foo=doo test=best', checks=[
            self.check('monitorConfig.expectedStatusCodeRanges[0].min', 200),
            self.check('monitorConfig.expectedStatusCodeRanges[0].max', 204),
            self.check('monitorConfig.customHeaders[0].name', 'foo'),
            self.check('monitorConfig.customHeaders[0].value', 'doo'),
            self.check('monitorConfig.customHeaders[1].name', 'test'),
            self.check('monitorConfig.customHeaders[1].value', 'best')
        ])

        # Endpoint tests
        self.cmd('network traffic-manager endpoint create -n {endpoint} --profile-name {tm} -g {rg} --type azureEndpoints --target-resource-id {ip_id} --subnets 10.0.0.0 --custom-headers test=best', checks=[
            self.check('customHeaders[0].name', 'test'),
            self.check('customHeaders[0].value', 'best'),
            self.check('subnets[0].first', '10.0.0.0')
        ])
        self.cmd('network traffic-manager endpoint update -n {endpoint} --type azureEndpoints --profile-name {tm} -g {rg} --subnets 10.0.0.0:24', checks=[
            self.check('subnets[0].first', '10.0.0.0'),
            self.check('subnets[0].scope', '24')
        ])
        self.cmd('network traffic-manager endpoint update -n {endpoint} --type azureEndpoints --profile-name {tm} -g {rg} --subnets 10.0.0.0-11.0.0.0', checks=[
            self.check('subnets[0].first', '10.0.0.0'),
            self.check('subnets[0].last', '11.0.0.0')
        ])

    @ResourceGroupPreparer('cli_test_traffic_manager_always_serve')
    def test_network_traffic_manager_always_serve(self, resource_group):
        self.kwargs.update({
            "profile": self.create_random_name("profile-", 12),
            "endpoint": self.create_random_name("endpoint-", 16),
            "dns": "mytrafficmanager001100a1",
        })

        self.cmd("network traffic-manager profile create -n {profile} -g {rg} --routing-method weighted --unique-dns-name {dns}")
        self.cmd(
            "network traffic-manager endpoint create -n {endpoint} -g {rg} --profile-name {profile} "
            "--type externalEndpoints --weight 50 --target www.microsoft.com --always-serve Enabled",
            checks=[
                self.check("type", "Microsoft.Network/trafficManagerProfiles/externalEndpoints"),
                self.check("alwaysServe", "Enabled"),
            ]
        )
        self.cmd(
            "network traffic-manager endpoint update -n {endpoint} -g {rg} --profile-name {profile} "
            "--type externalEndpoints --weight 25 --target www.contoso.com --always-serve Disabled",
            checks=[
                self.check("weight", 25),
                self.check("target", "www.contoso.com"),
                self.check("alwaysServe", "Disabled"),
            ]
        )

    @ResourceGroupPreparer('cli_test_traffic_manager_record_type')
    def test_network_traffic_manager_record_type(self, resource_group):
        self.kwargs.update({
            'tm': 'mytmprofile-rt',
            'dns': self.create_random_name('testtmrt', 20),
            'endpoint': 'myendpoint-rt',
        })

        # Create a profile with record-type A
        self.cmd(
            'network traffic-manager profile create -n {tm} -g {rg} '
            '--routing-method priority --unique-dns-name {dns} --record-type A',
            checks=[
                self.check('TrafficManagerProfile.recordType', 'A'),
            ]
        )

        # Verify record-type is returned on show
        self.cmd(
            'network traffic-manager profile show -g {rg} -n {tm}',
            checks=[
                self.check('recordType', 'A'),
                self.check('dnsConfig.relativeName', '{dns}'),
            ]
        )

        # Verify record-type is returned on list
        self.cmd(
            'network traffic-manager profile list -g {rg}',
            checks=[
                self.check('length(@)', 1),
                self.check('[0].recordType', 'A'),
            ]
        )

        # Clean up
        self.cmd('network traffic-manager profile delete -g {rg} -n {tm}')

    @ResourceGroupPreparer('cli_test_traffic_manager_record_type_update')
    def test_network_traffic_manager_record_type_update(self, resource_group):
        self.kwargs.update({
            'tm': 'mytmprofile-rtu',
            'dns': self.create_random_name('testtmrtu', 20),
            'endpoint': 'myendpoint-rtu',
        })

        # Create a profile without record-type
        self.cmd(
            'network traffic-manager profile create -n {tm} -g {rg} '
            '--routing-method priority --unique-dns-name {dns}',
            checks=[
                self.check('TrafficManagerProfile.recordType', None),
            ]
        )

        # Show and confirm no record-type
        self.cmd(
            'network traffic-manager profile show -g {rg} -n {tm}',
            checks=[
                self.check('recordType', None),
            ]
        )

        # Add an endpoint with IPv4 target
        self.cmd(
            'network traffic-manager endpoint create -n {endpoint} --profile-name {tm} -g {rg} '
            '--type externalEndpoints --weight 50 --target 10.0.0.1',
            checks=[
                self.check('type', 'Microsoft.Network/trafficManagerProfiles/externalEndpoints'),
            ]
        )

        # Show and confirm still no record-type
        self.cmd(
            'network traffic-manager profile show -g {rg} -n {tm}',
            checks=[
                self.check('recordType', None),
                self.check('length(endpoints)', 1),
            ]
        )

        # Update the profile to set record-type A
        self.cmd(
            'network traffic-manager profile update -n {tm} -g {rg} --record-type A',
            checks=[
                self.check('recordType', 'A'),
            ]
        )

        # Show and confirm record-type is set and endpoint still exists
        self.cmd(
            'network traffic-manager profile show -g {rg} -n {tm}',
            checks=[
                self.check('recordType', 'A'),
                self.check('length(endpoints)', 1),
                self.check('endpoints[0].name', '{endpoint}'),
            ]
        )

        # Clean up
        self.cmd('network traffic-manager endpoint delete -g {rg} --profile-name {tm} -t externalEndpoints -n {endpoint}')
        self.cmd('network traffic-manager profile delete -g {rg} -n {tm}')


class NetworkWatcherConfigureScenarioTest(LiveScenarioTest):

    @ResourceGroupPreparer(name_prefix='cli_test_nw', location='westcentralus')
    def test_network_watcher_configure(self, resource_group):
        self.cmd('network watcher configure -g {rg} --locations westus westus2 westcentralus eastus canadaeast --enabled')
        self.cmd('network watcher configure --locations westus westus2 eastus canadaeast --tags foo=doo')
        self.cmd('network watcher configure -l westus2 --enabled false')
        self.cmd('network watcher list')


class NetworkWatcherScenarioTest(ScenarioTest):
    from unittest import mock

    def _mock_thread_count(self):
        return 1

    @mock.patch('azure.cli.command_modules.vm._actions._get_thread_count', _mock_thread_count)
    @ResourceGroupPreparer(name_prefix='cli_test_nw_vm', location='westcentralus')
    @AllowLargeResponse()
    def test_network_watcher_vm(self, resource_group, resource_group_location):

        self.kwargs.update({
            'loc': 'westcentralus',
            'vm': 'vm1',
            'nsg': 'nsg1',
            'capture': 'capture1',
            'private-ip': '10.0.0.9',
            'subnet': 'subnet1',
            'vnet': 'vnet1'
        })

        vm = self.cmd('vm create -g {rg} -n {vm} --image Canonical:UbuntuServer:18.04-LTS:latest --authentication-type password --admin-username deploy '
                      '--admin-password PassPass10!) --nsg {nsg} --nsg-rule None --private-ip-address {private-ip} --subnet {subnet} --vnet-name {vnet}').get_output_in_json()

        # Disable default outbound access
        self.cmd('network vnet subnet update -g {rg} --vnet-name {vnet} -n {subnet} --default-outbound-access false')

        self.kwargs['vm_id'] = vm['id']
        self.cmd('vm extension set -g {rg} --vm-name {vm} -n NetworkWatcherAgentLinux --publisher Microsoft.Azure.NetworkWatcher')

        self.cmd('network watcher test-connectivity -g {rg} --source-resource {vm} --dest-address www.microsoft.com --dest-port 80 --valid-status-codes 200 202')
        self.cmd('network watcher run-configuration-diagnostic --resource {vm_id} --direction Inbound --protocol TCP --source 12.11.12.14 --destination 10.1.1.4 --port 12100')
        self.cmd('network watcher show-topology -g {rg}')
        self.cmd('network watcher test-ip-flow -g {rg} --vm {vm} --direction inbound --local {private-ip}:22 --protocol tcp --remote 100.1.2.3:*')
        self.cmd('network watcher test-ip-flow -g {rg} --vm {vm} --direction outbound --local {private-ip}:* --protocol tcp --remote 100.1.2.3:80')
        self.cmd('network watcher show-security-group-view -g {rg} --vm {vm}')
        self.cmd('network watcher show-next-hop -g {rg} --vm {vm} --source-ip 10.0.0.9 --dest-ip 10.0.0.6')

    @mock.patch('azure.cli.command_modules.vm._actions._get_thread_count', _mock_thread_count)
    @ResourceGroupPreparer(name_prefix='cli_test_nw_packet_capture', location='westus2')
    @AllowLargeResponse()
    def test_network_watcher_packet_capture(self, resource_group, resource_group_location):

        self.kwargs.update({
            'loc': resource_group_location,
            'vm': 'vm1',
            'capture1': 'capture1',
            'capture2': 'capture2',
            'subnet': 'subnet1',
            'vnet': 'vnet1'
        })

        self.cmd('vm create -g {rg} -n {vm} --image Canonical:UbuntuServer:16.04-LTS:latest --authentication-type password --admin-username deploy '
                 '--admin-password PassPass10!) --nsg {vm} --subnet {subnet} --vnet-name {vnet} --nsg-rule None --size Standard_D2s_v3')

        # Disable default outbound access
        self.cmd('network vnet subnet update -g {rg} --vnet-name {vnet} -n {subnet} --default-outbound-access false')

        self.cmd('vm extension set -g {rg} --vm-name {vm} -n NetworkWatcherAgentLinux --publisher Microsoft.Azure.NetworkWatcher')

        self.cmd('network watcher packet-capture create -g {rg} --vm {vm} -n {capture1} --file-path capture/capture.cap')
        self.cmd('network watcher packet-capture create -g {rg} --vm {vm} -n {capture2} --file-path capture/capture.cap --target-type AzureVM')
        self.cmd('network watcher packet-capture show -l {loc} -n {capture1}')
        self.cmd('network watcher packet-capture stop -l {loc} -n {capture1}')
        self.cmd('network watcher packet-capture show-status -l {loc} -n {capture1}')
        self.cmd('network watcher packet-capture list -l {loc}')
        self.cmd('network watcher packet-capture delete -l {loc} -n {capture1}')
        self.cmd('network watcher packet-capture delete -l {loc} -n {capture2}')
        self.cmd('network watcher packet-capture list -l {loc}')

    @mock.patch('azure.cli.command_modules.vm._actions._get_thread_count', _mock_thread_count)
    @ResourceGroupPreparer(name_prefix='cli_test_nw_packet_capture_vmss_as_target', location='westcentralus')
    @AllowLargeResponse()
    def test_network_watcher_packet_capture_vmss_as_target(self, resource_group, resource_group_location):

        self.kwargs.update({
            'loc': resource_group_location,
            'vmss': 'vmssForPcap',
            'capture': 'captureVmss',
            'capture1': 'captureVMSS1',
            'capture2': 'captureVMSS2'
        })
        self.cmd('vmss create -g {rg} --name {vmss} --image Canonical:UbuntuServer:16.04-LTS:latest --location {loc} --admin-username azureuser --generate-ssh-keys --upgrade-policy-mode Automatic --vm-sku Standard_D2s_v3 --orchestration-mode Uniform')
        self.cmd('vmss extension set --name NetworkWatcherAgentLinux --publisher Microsoft.Azure.NetworkWatcher --resource-group {rg} --vmss-name  {vmss}')

        self.cmd('network watcher packet-capture create -g {rg} --target {vmss} -n {capture} --target-type AzureVMSS --file-path capture/capture.cap', checks=[
            self.check('provisioningState', 'Succeeded')
        ])
        self.cmd('network watcher packet-capture create -g {rg} --target {vmss} -n {capture1} --target-type AzureVMSS --file-path capture/capture.cap --exclude 1')
        self.cmd('network watcher packet-capture create -g {rg} --target {vmss} -n {capture2} --target-type AzureVMSS --file-path capture/capture.cap --include 0 1')
        self.cmd('network watcher packet-capture show -l {loc} -n {capture}')
        self.cmd('network watcher packet-capture stop -l {loc} -n {capture}')
        self.cmd('network watcher packet-capture show-status -l {loc} -n {capture}')
        self.cmd('network watcher packet-capture list -l {loc}')
        self.cmd('network watcher packet-capture delete -l {loc} -n {capture}')
        self.cmd('network watcher packet-capture delete -l {loc} -n {capture1}')
        self.cmd('network watcher packet-capture delete -l {loc} -n {capture2}')
        self.cmd('network watcher packet-capture list -l {loc}')

    @ResourceGroupPreparer(name_prefix='cli_test_nw_troubleshooting', location='westcentralus')
    @StorageAccountPreparer(name_prefix='clitestnw', location='westcentralus')
    @AllowLargeResponse()
    def test_network_watcher_troubleshooting(self, resource_group, resource_group_location, storage_account):

        self.kwargs.update({
            'loc': resource_group_location,
            'sa': storage_account
        })

        # set up resource to troubleshoot
        self.cmd('storage container create -n troubleshooting --account-name {sa}')
        sa = self.cmd('storage account show -g {rg} -n {sa}').get_output_in_json()
        self.kwargs['storage_path'] = sa['primaryEndpoints']['blob'] + 'troubleshooting'
        self.cmd('network vnet create -g {rg} -n vnet1 --subnet-name GatewaySubnet')
        self.cmd('network public-ip create -g {rg} -n vgw1-pip')
        self.cmd('network vnet-gateway create -g {rg} -n vgw1 --vnet vnet1 --public-ip-address vgw1-pip')

        # test troubleshooting
        self.cmd('network watcher troubleshooting start --resource vgw1 -t vnetGateway -g {rg} --storage-account {sa} --storage-path {storage_path}')
        self.cmd('network watcher troubleshooting show --resource vgw1 -t vnetGateway -g {rg}')


class ServiceEndpointScenarioTest(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='network_service_endpoint_scenario_test', location='westcentralus')
    def test_network_service_endpoints(self, resource_group, resource_group_location):

        self.kwargs.update({
            'policy': 'policy1',
            'pd_name': 'storage-def',
            'sub': self.get_subscription_id(),
            'vnet': 'vnet1',
            'subnet': 'subnet1',
            'loc': resource_group_location
        })

        self.cmd('network service-endpoint list -l {loc}')

        # test policy CRUD
        self.cmd('network service-endpoint policy create -g {rg} -n {policy} --tags test=best',
                 checks=self.check('tags.test', 'best'))
        self.cmd('network service-endpoint policy update -g {rg} -n {policy} --tags test=nest',
                 checks=self.check('tags.test', 'nest'))
        self.cmd('network service-endpoint policy list -g {rg}',
                 checks=self.check('length(@)', 1))
        self.cmd('network service-endpoint policy show -g {rg} -n {policy}',
                 checks=self.check('tags.test', 'nest'))
        self.cmd('network service-endpoint policy delete -g {rg} -n {policy}')
        self.cmd('network service-endpoint policy list -g {rg}',
                 checks=self.check('length(@)', 0))

        # test policy definition CRUD
        self.cmd('network service-endpoint policy create -g {rg} -n {policy} --tags test=best')
        self.cmd('network service-endpoint policy-definition create -g {rg} --policy-name {policy} -n {pd_name} --service Microsoft.Storage --description "Test Def" --service-resources /subscriptions/{sub}', checks=[
            self.check("length(serviceResources)", 1),
            self.check('service', 'Microsoft.Storage'),
            self.check('description', 'Test Def')
        ])
        self.cmd('network service-endpoint policy-definition update -g {rg} --policy-name {policy} -n {pd_name} --description "Better description"',
                 self.check('description', 'Better description'))
        self.cmd('network service-endpoint policy-definition list -g {rg} --policy-name {policy}',
                 checks=self.check('length(@)', 1))
        self.cmd('network service-endpoint policy-definition show -g {rg} --policy-name {policy} -n {pd_name}',
                 checks=self.check('description', 'Better description'))
        self.cmd('network service-endpoint policy-definition delete -g {rg} --policy-name {policy} -n {pd_name}')
        self.cmd('network service-endpoint policy-definition list -g {rg} --policy-name {policy}',
                 checks=self.check('length(@)', 0))

        # create a subnet with the policy
        self.cmd('network service-endpoint policy-definition create -g {rg} --policy-name {policy} -n {pd_name} --service Microsoft.Storage --service-resources /subscriptions/{sub}')
        self.cmd('network vnet create -g {rg} -n {vnet}')
        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} -n {subnet} --address-prefix 10.0.0.0/24 --service-endpoints Microsoft.Storage --service-endpoint-policy {policy} --default-outbound false',
                 checks=self.check("contains(serviceEndpointPolicies[0].id, '{policy}')", True))


class NetworkProfileScenarioTest(ScenarioTest):

    @live_only()
    @ResourceGroupPreparer(name_prefix='test_network_profile')
    def test_network_profile(self, resource_group):

        # no e2e scenario without create. Testing path to service only.
        self.cmd('network profile list')
        self.cmd('network profile list -g {rg}')
        with self.assertRaisesRegex(SystemExit, '3'):
            self.cmd('network profile show -g {rg} -n dummy')
        self.cmd('network profile delete -g {rg} -n dummy -y')


class NetworkServiceAliasesScenarioTest(ScenarioTest):

    @AllowLargeResponse(size_kb=99999)
    @ResourceGroupPreparer(name_prefix='test_network_service_aliases')
    def test_network_service_aliases(self, resource_group):
        self.kwargs.update({
            'rg': resource_group
        })
        self.cmd('network list-service-aliases -l centralus', checks=self.check('type(@)', 'array'))
        self.cmd('network list-service-aliases -l centralus -g {rg}', checks=self.check('type(@)', 'array'))

        # test list-service-tags
        self.cmd('network list-service-tags -l centralus', checks=self.check('type(@)', 'object'))


class NetworkVirtualNetworkGatewayNatRule(ScenarioTest):

    @ResourceGroupPreparer()
    def test_network_vnet_gateway_nat_rule(self, resource_group):
        self.kwargs.update({
            'rg': resource_group,
            'ip': 'ip',
            'ip1': 'ip1',
            'vnet': 'vnet',
            'vnet1': 'vnet1',
            'subnet': 'GatewaySubnet',
            'vg': 'vnet-gateway-name',
            'vg1': 'vnet-gateway-name1',
            'sku': 'VpnGw2',
        })

        # minimal parameters
        self.cmd('network public-ip create -g {rg} -n {ip}')
        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name {subnet}')
        self.cmd('network vnet-gateway create -g {rg} -n {vg} --vnet {vnet} --public-ip-address {ip}  --sku {sku} '
                 '--nat-rule name=nat internal-mappings=10.4.0.0/24 external-mappings=192.168.21.0/24 ',
                 checks=[self.check('length(vnetGateway.natRules)', 1)])
        self.cmd("network vnet-gateway show -n {vg} -g {rg}")
        self.cmd("network vnet-gateway list -g {rg}")

        # minimal parameters(ip-config-id can only be set when type is Dynamic, and only allowlist sub-ids support Dynamic)
        self.cmd('network public-ip create -g {rg} -n {ip1}')
        self.cmd('network vnet create -g {rg} -n {vnet1} --subnet-name {subnet}')
        self.cmd('network vnet-gateway create -g {rg} -n {vg1} --vnet {vnet1} --public-ip-address {ip1}  --sku {sku} '
                 '--nat-rule name=nat type=Static mode=EgressSnat internal-mappings=10.4.0.0/24 '
                 'external-mappings=192.168.21.0/24',
                 checks=[self.check('length(vnetGateway.natRules)', 1)])

        # test vnet-gateway reset
        self.cmd('network vnet-gateway reset -g {rg} -n {vg}')

    @ResourceGroupPreparer()
    def test_network_vnet_gateway_nat_rule_sub_cmd(self, resource_group):
        self.kwargs.update({
            'rg': resource_group,
            'ip': 'ip',
            'vnet': 'vnet',
            'subnet': 'GatewaySubnet',
            'vg': 'vnet-gateway-name',
            'sku': 'VpnGw2',
            'nat': 'nat-rule-name',
            'nat1': 'nat-rule-name1',
        })

        # minimal parameters
        self.cmd('network public-ip create -g {rg} -n {ip}')
        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name {subnet}')
        self.cmd('network vnet-gateway create -g {rg} -n {vg} --vnet {vnet} --public-ip-address {ip}  --sku {sku}')

        # sub cmd
        self.cmd('network vnet-gateway nat-rule add -g {rg} --gateway-name {vg} --name {nat} '
                 '--internal-mappings 10.4.0.0/24 --external-mappings 192.168.21.0/24',
                 checks=[self.check('length(natRules)', 1)])

        self.cmd('network vnet-gateway nat-rule add -g {rg} --gateway-name {vg} --name {nat1} '
                 '--internal-mappings 10.3.0.0/24 --external-mappings 192.168.22.0/24',
                 checks=[self.check('length(natRules)', 2)])

        self.cmd('network vnet-gateway nat-rule list -g {rg} --gateway-name {vg} ',
                 checks=[self.check('length(@)', 2)])

        self.cmd('network vnet-gateway nat-rule remove -g {rg} --gateway-name {vg} --name {nat}',
                 checks=[self.check('length(natRules)', 1)])


class NetworkSecurityPartnerProviderScenarioTest(ScenarioTest):
    def __init__(self, method_name, config_file=None, recording_dir=None, recording_name=None, recording_processors=None,
                 replay_processors=None, recording_patches=None, replay_patches=None):
        super().__init__(method_name)
        self.cmd('extension add -n virtual-wan')

    @unittest.skip('Decouple with virtual-wan bump API version')
    @ResourceGroupPreparer(name_prefix='cli_test_security_partner_provider_', location='westus')
    @AllowLargeResponse()
    def test_network_security_partner_provider(self):
        self.kwargs.update({
            'vwan': 'clitestvwan',
            'vhub': 'clitestvhub',
            'gateway': 'cligateway',
            'name': 'clisecuritypartnerprovider'
        })

        self.cmd('network vwan create -n {vwan} -g {rg} --type Standard')
        self.cmd('network vhub create -g {rg} -n {vhub} --vwan {vwan} --address-prefix 10.5.0.0/16 --sku Standard')
        self.cmd('network vpn-gateway create -g {rg} -n {gateway} --vhub {vhub}')

        self.cmd('network security-partner-provider create -n {name} -g {rg} --vhub {vhub} --provider Checkpoint', checks=[
            self.check('name', '{name}'),
            self.check('securityProviderName', 'Checkpoint')
        ])
        self.cmd('network security-partner-provider show -n {name} -g {rg}', checks=[
            self.check('name', '{name}'),
            self.check('securityProviderName', 'Checkpoint')
        ])
        self.cmd('network security-partner-provider update -n {name} -g {rg} --tag a=b', checks=[
            self.check('tags.a', 'b')
        ])
        self.cmd('network security-partner-provider list -g {rg}', checks=[
            self.check('length(@)', 1)
        ])
        self.cmd('network security-partner-provider list', checks=[
            self.check('length(@)', 1)
        ])
        self.cmd('network security-partner-provider delete -n {name} -g {rg}')


class NetworkVirtualApplianceScenarioTest(ScenarioTest):
    def setUp(self):
        super().setUp()
        self.cmd('extension add -n virtual-wan')

    def tearDown(self):
        # avoid influence other test when parallel run
        # self.cmd('extension remove -n virtual-wan')
        super().tearDown()

    @unittest.skip('GatewayError')
    @ResourceGroupPreparer(location='westcentralus', name_prefix='test_network_virtual_appliance')
    @AllowLargeResponse()
    def test_network_virtual_appliance(self, resource_group):
        self.kwargs.update({
            'vwan': 'clitestvwan',
            'vhub': 'clitestvhub',
            'name': 'cli-virtual-appliance',
            'site': 'cli-site',
            'blob': 'https://azurecliprod.blob.core.windows.net/cli-extensions/account-0.1.0-py2.py3-none-any.whl',
            'rg': resource_group
        })

        self.cmd('network vwan create -n {vwan} -g {rg} --type Standard')
        self.cmd('network vhub create -g {rg} -n {vhub} --vwan {vwan} --address-prefix 10.5.0.0/16 --sku Standard')

        self.cmd('network virtual-appliance create -n {name} -g {rg} --vhub {vhub} --vendor "barracudasdwanrelease" '
                 '--scale-unit 2 -v latest --asn 10000 --init-config "echo $abc" '
                 '--boot-blobs {blob} {blob} --cloud-blobs {blob} {blob}',
                 checks=[
                     self.check('name', '{name}'),
                     self.check('length(bootStrapConfigurationBlobs)', 2),
                     self.check('length(cloudInitConfigurationBlobs)', 2),
                     self.check('virtualApplianceAsn', 10000),
                     self.check('cloudInitConfiguration', "echo $abc")
                 ])
        self.cmd('network virtual-appliance update -n {name} -g {rg} --asn 20000 --init-config "echo $abcd"', checks=[
            self.check('virtualApplianceAsn', 20000),
            self.check('cloudInitConfiguration', "echo $abcd")
        ])
        self.cmd('network virtual-appliance show -n {name} -g {rg}', checks=[
            self.check('name', '{name}'),
            self.check('length(bootStrapConfigurationBlobs)', 2),
            self.check('length(cloudInitConfigurationBlobs)', 2),
            self.check('virtualApplianceAsn', 20000),
            self.check('cloudInitConfiguration', "echo $abcd")
        ])
        self.cmd('network virtual-appliance list -g {rg}', checks=[
            self.check('length(@)', 1)
        ])
        self.cmd('network virtual-appliance list', checks=[
            self.check('length(@)', 1)
        ])

        self.cmd('network virtual-appliance sku list', checks=[
            self.check('length(@)', 3)
        ])
        self.cmd('network virtual-appliance sku show --name "barracudasdwanrelease"', checks=[
            self.check('name', 'barracudasdwanrelease')
        ])

        self.cmd('network virtual-appliance site create -n {site} -g {rg} --appliance-name {name} --address-prefix 10.0.0.0/24 --allow --default --optimize', checks=[
            self.check('name', '{site}'),
            self.check('o365Policy.breakOutCategories.allow', True),
            self.check('o365Policy.breakOutCategories.default', True),
            self.check('o365Policy.breakOutCategories.optimize', True),
            self.check('addressPrefix', '10.0.0.0/24')
        ])
        self.cmd('network virtual-appliance site update -n {site} -g {rg} --appliance-name {name} --address-prefix 10.0.0.1/24 --allow false --default false --optimize false', checks=[
            self.check('name', '{site}'),
            self.check('o365Policy.breakOutCategories.allow', False),
            self.check('o365Policy.breakOutCategories.default', False),
            self.check('o365Policy.breakOutCategories.optimize', False),
            self.check('addressPrefix', '10.0.0.1/24')
        ])
        self.cmd('network virtual-appliance site show -n {site} -g {rg} --appliance-name {name}', checks=[
            self.check('name', '{site}'),
            self.check('o365Policy.breakOutCategories.allow', False),
            self.check('o365Policy.breakOutCategories.default', False),
            self.check('o365Policy.breakOutCategories.optimize', False),
            self.check('addressPrefix', '10.0.0.1/24')
        ])
        self.cmd('network virtual-appliance site list -g {rg} --appliance-name {name}', checks=[
            # self.check('length(@)', 1)
        ])
        self.cmd('network virtual-appliance site delete -n {site} -g {rg} --appliance-name {name} -y')
        self.cmd('network virtual-appliance delete -n {name} -g {rg} -y')



class NetworkVirtualApplianceIdentityScenarioTest(ScenarioTest):
    @live_only()
    @ResourceGroupPreparer(location='westcentralus', name_prefix='test_network_virtual_appliance_identity')
    @AllowLargeResponse(size_kb=9999)
    def test_network_virtual_appliance_identity(self, resource_group):
        from time import sleep
        self.kwargs.update({
            'vwan': 'clitestvwan',
            'vhub': 'clittestvhub',
            'nva_name1': 'cli-virtual-appliance1',
            'nva_name2': 'cli-virtual-appliance2',
            'nva_name3': 'cli-virtual-appliance3',
            'nva_name4': 'cli-virtual-appliance4',
            'nva_name5': 'cli-virtual-appliance5',
            'nva_name6': 'cli-virtual-appliance6',
            'rg': resource_group,
            'ua_Identity1': 'cli-ua-identity1',
            'ua_Identity2': 'cli-ua-identity2'
        })
        self.cmd('extension add -n virtual-wan')
        self.cmd('network vwan create -n {vwan} -g {rg} --type Standard')
        self.cmd('network vhub create -g {rg} -n {vhub} --vwan {vwan} --address-prefix 10.5.0.0/16 --sku Standard')
        routing_state = self.cmd('network vhub show -g {rg} -n {vhub}').get_output_in_json()['routingState']
        retry_count = 0
        while routing_state != 'Provisioned':
            if retry_count == 20:
                break
            retry_count += 1
            sleep(360)
            routing_state = self.cmd('network vhub show -g {rg} -n {vhub}').get_output_in_json()['routingState']
        identityProperty1 = '{"type":"SystemAssigned"}'
        self.kwargs.update({
            'identityProperty1': identityProperty1
        })
        self.cmd('network virtual-appliance create -n {nva_name3} -g {rg} --vhub {vhub} --vendor "checkpoint" '
                 '--scale-unit 2 -v latest --asn 64512 --init-config "echo $abc" ',
                 checks=[
                     self.check('name', '{nva_name3}'),
                     self.check('virtualApplianceAsn', 64512),
                     self.check('cloudInitConfiguration', 'echo $abc')
                     ])
        self.cmd('network virtual-appliance show -g {rg} -n {nva_name3}', 
                 checks=[
                     self.check('name', '{nva_name3}'),
                     self.check('virtualApplianceAsn', 64512),
                     self.check('cloudInitConfiguration', 'echo $abc')
                     ])
        self.cmd('network virtual-appliance create -n {nva_name4} -g {rg} --vhub {vhub} --vendor "checkpoint" '
                 '--scale-unit 2 -v latest --asn 64512 --init-config "echo $abc" ',
                 checks=[
                     self.check('name', '{nva_name4}'),
                     self.check('virtualApplianceAsn', 64512),
                     self.check('cloudInitConfiguration', 'echo $abc')
                 ])
        self.cmd('network virtual-appliance show -g {rg} -n {nva_name4}', 
                 checks=[
                     self.check('name', '{nva_name4}'),
                     self.check('virtualApplianceAsn', 64512),
                     self.check('cloudInitConfiguration', 'echo $abc')
                     ])
        self.cmd('network virtual-appliance create -n {nva_name1} -g {rg} --vhub {vhub} --vendor "checkpoint" '
                 '--scale-unit 2 -v latest --asn 64512 --init-config "echo $abc" --identity {identityProperty1}',
                 checks=[
                     self.check('name', '{nva_name1}'),
                     self.check('virtualApplianceAsn', 64512),
                     self.check('cloudInitConfiguration', 'echo $abc'),
                     self.check('identity.type', 'SystemAssigned')
                     ])
        self.cmd('network virtual-appliance show -g {rg} -n {nva_name1}', 
                 checks=[
                     self.check('name', '{nva_name1}'),
                     self.check('virtualApplianceAsn', 64512),
                     self.check('cloudInitConfiguration', 'echo $abc'),
                     self.check('identity.type', 'SystemAssigned')
                     ])
        self.cmd('network virtual-appliance delete -n {nva_name1} -g {rg} -y')
        self.cmd('identity create -g {rg} -n {ua_Identity1}').get_output_in_json()
        subscriptionId = self.get_subscription_id()
        uaIdentity1 = self.kwargs.get('ua_Identity1')
        resourceGroup = self.kwargs.get('rg')
        identityProperty2 = '{"type":"UserAssigned","userAssignedIdentities":{"/subscriptions/"' + subscriptionId + '"/resourceGroups/"' + resourceGroup + '"/providers/Microsoft.ManagedIdentity/userAssignedIdentities/"' + uaIdentity1 + ':{}}}'
        self.kwargs.update({
            'identityProperty2': identityProperty2
        })
        self.cmd('network virtual-appliance create -n {nva_name2} -g {rg} --vhub {vhub} --vendor "checkpoint" '
                 '--scale-unit 2 -v latest --asn 64512 --init-config "echo $abc" --identity {identityProperty2} ',
                 checks=[
                     self.check('name', '{nva_name2}'),
                     self.check('virtualApplianceAsn', 64512),
                     self.check('cloudInitConfiguration', 'echo $abc'),
                     self.check('identity.type', 'UserAssigned')
                     ])
        self.cmd('network virtual-appliance show -g {rg} -n {nva_name2}', 
                 checks=[
                     self.check('name', '{nva_name2}'),
                     self.check('virtualApplianceAsn', 64512),
                     self.check('cloudInitConfiguration', 'echo $abc'),
                     self.check('identity.type', 'UserAssigned')
                     ])
        self.cmd('network virtual-appliance delete -n {nva_name2} -g {rg} -y')
        identityProperty3 = '{"type":"SystemAssigned"}'
        self.kwargs.update({
            'identityProperty3': identityProperty3
        })
        self.cmd('network virtual-appliance update -g {rg} -n {nva_name3} --identity {identityProperty3}',
                 checks=[
                     self.check('name', '{nva_name3}'),
                     self.check('virtualApplianceAsn', 64512),
                     self.check('cloudInitConfiguration', 'echo $abc'),
                     self.check('identity.type', 'SystemAssigned')
                 ])
        self.cmd('network virtual-appliance delete -n {nva_name3} -g {rg} -y')

        self.cmd('identity create -g {rg} -n {ua_Identity2}').get_output_in_json()
        uaIdentity2 = self.kwargs.get('ua_Identity2')
        identityProperty4 = '{"type":"UserAssigned","userAssignedIdentities":{"/subscriptions/"' + subscriptionId + '"/resourceGroups/"' + resourceGroup + '"/providers/Microsoft.ManagedIdentity/userAssignedIdentities/"' + uaIdentity2 + ':{}}}'
        self.kwargs.update({
            'identityProperty4': identityProperty4
        })
        self.cmd('network virtual-appliance update -g {rg} -n {nva_name4} --identity {identityProperty4}',
                 checks=[
                     self.check('name', '{nva_name4}'),
                     self.check('virtualApplianceAsn', 64512),
                     self.check('cloudInitConfiguration', 'echo $abc'),
                     self.check('identity.type', 'UserAssigned')
                 ])
        self.cmd('network virtual-appliance delete -n {nva_name4} -g {rg} -y')

class NetworkVirtualApplianceConnectionScenarioTest(ScenarioTest):
    @live_only()
    @ResourceGroupPreparer(location='westcentralus', name_prefix='test_network_virtual_appliance_connection')
    @AllowLargeResponse(size_kb=9999)
    def test_network_virtual_appliance_connection(self, resource_group):
        from time import sleep
        subscriptionId = self.get_subscription_id()
        self.kwargs.update({
            'vwan': 'clitestvwan',
            'vhub': 'clittestvhub',
            'nva_name': 'clivirtualappliance',
            'rg': resource_group,
            'name': 'defaultConnection',
            'subscription': subscriptionId
        })
        self.cmd('extension add -n virtual-wan')
        self.cmd('network vwan create -n {vwan} -g {rg} --type Standard')
        self.cmd('network vhub create -g {rg} -n {vhub} --vwan {vwan} --address-prefix 10.5.0.0/16 --sku Standard')
        routing_state = self.cmd('network vhub show -g {rg} -n {vhub}').get_output_in_json()['routingState']
        retry_count = 0
        while routing_state != 'Provisioned':
            if retry_count == 20:
                break
            retry_count += 1
            sleep(360)
            routing_state = self.cmd('network vhub show -g {rg} -n {vhub}').get_output_in_json()['routingState']
        self.cmd('network virtual-appliance create -n {nva_name} -g {rg} --vhub {vhub} --vendor "checkpoint" '
                 '--scale-unit 2 -v latest --asn 64512 --init-config "echo $abc" ',
                 checks=[
                     self.check('name', '{nva_name}'),
                     self.check('virtualApplianceAsn', 64512),
                     self.check('cloudInitConfiguration', 'echo $abc')
                 ])
        self.cmd('network virtual-appliance show -g {rg} -n {nva_name}', 
                 checks=[
                     self.check('name', '{nva_name}'),
                     self.check('virtualApplianceAsn', 64512),
                     self.check('cloudInitConfiguration', 'echo $abc')
                     ])
        self.cmd('network virtual-appliance connection show -n {name} -g {rg} --nva {nva_name} --subscription {subscription}', checks=[
            self.check('name', '{name}')
        ])

        self.cmd('network virtual-appliance connection list -g {rg} --nva {nva_name} --subscription {subscription}', checks=[
            self.check('length(@)', 1)
        ])

        self.cmd('network virtual-appliance connection update '
                 '-n {name} '
                 '-g {rg} '
                 '--nva {nva_name} '
                 '--labels [label1,label2] ')
        
        self.cmd('network virtual-appliance connection show -n {name} -g {rg} --nva {nva_name} --subscription {subscription}', checks=[
            self.check('length(properties.routingConfiguration.propagatedRouteTables.labels)', 2),
            self.check('properties.routingConfiguration.propagatedRouteTables.labels[0]', 'label1')
        ])

    @record_only()
    def test_get_boot(self):
        self.cmd('network virtual-appliance get-boot-diagnostic-log -n chkptbd1031 -g nashoktest --scs-sas-url "https://stonashoktest.blob.core.windows.net/testcontainer/example.txt?sp=rw&st=2025-03-07T03:47:49Z&se=2025-03-08T11:47:49Z&skoid=7f5b7efd-fa3f-4fbd-9430-8cf0f0ca6822&sktid=72f988bf-86f1-41af-91ab-2d7cd011db47&skt=2025-03-07T03:47:49Z&ske=2025-03-08T11:47:49Z&sks=b&skv=2022-11-02&spr=https&sv=2022-11-02&sr=b&sig=TOSsTfWx3e6ti7YLmeYms%2B3hAwMUSTlilE%2F08iht%2BUc%3D" --css-sas-url "https://stonashoktest.blob.core.windows.net/testcontainer/pstestscreenshot.png?sp=rw&st=2025-03-07T03:48:23Z&se=2025-03-08T11:48:23Z&skoid=7f5b7efd-fa3f-4fbd-9430-8cf0f0ca6822&sktid=72f988bf-86f1-41af-91ab-2d7cd011db47&skt=2025-03-07T03:48:23Z&ske=2025-03-08T11:48:23Z&sks=b&skv=2022-11-02&spr=https&sv=2022-11-02&sr=b&sig=4rU9xYe4T6t8GDUI0SVOhywiQWxIEtRSytpzq0xKwWY%3D"')


class NetworkVirtualApplianceReimageScenarioTest(ScenarioTest):
    @live_only()
    @ResourceGroupPreparer(location='eastus2euap', name_prefix='test_network_virtual_appliance_reimage')
    @AllowLargeResponse(size_kb=9999)
    def test_network_virtual_appliance_reimage(self, resource_group):
        from time import sleep

        # Variables to use in the test
        subscriptionId = self.get_subscription_id()
        self.kwargs.update({
            'vwan': 'clitestvwan',  # Virtual WAN name
            'vhub': 'clivhub',  # Virtual Hub name
            'nva_name': 'clivirtualappliancereimage',  # NVA name
            'rg': resource_group,
            'name': 'defaultConnection',
            'subscription': subscriptionId,
            'instance_id' : 0
        })

        # Add the required extension
        self.cmd('extension add -n virtual-wan')
        
        # Create Virtual WAN
        self.cmd('network vwan create -n {vwan} -g {rg} --type Standard', checks=[
            self.check('name', '{vwan}'),
            self.check('type', 'Microsoft.Network/virtualWans')
        ])
        
        # Create Virtual Hub within the Virtual WAN
        self.cmd('network vhub create -g {rg} -n {vhub} --vwan {vwan} --address-prefix 10.5.0.0/16 --sku Standard', checks=[
            self.check('name', '{vhub}'),
        ])

        routing_state = self.cmd('network vhub show -g {rg} -n {vhub}').get_output_in_json()['routingState']
        retry_count = 0
        while routing_state != 'Provisioned':
            if retry_count == 20:
                break
            retry_count += 1
            sleep(360)
            routing_state = self.cmd('network vhub show -g {rg} -n {vhub}').get_output_in_json()['routingState']

        # Create the NVA
        self.cmd('network virtual-appliance create -n {nva_name} -g {rg} --vhub clivhub --vendor "checkpoint" '
                 '--scale-unit 2 -v latest --asn 64512 --init-config "echo $abc"',
                 checks=[
                     self.check('name', '{nva_name}'),
                     self.check('virtualApplianceAsn', 64512),
                     self.check('cloudInitConfiguration', 'echo $abc')
                 ])

        # Verify the NVA exists
        self.cmd('network virtual-appliance show -g {rg} -n {nva_name}',
                 checks=[
                     self.check('name', '{nva_name}'),
                     self.check('virtualApplianceAsn', 64512),
                     self.check('cloudInitConfiguration', 'echo $abc')
                 ])

        # Trigger the reimage operation (you won't get useful data in response, just confirm the request is accepted)
        response = self.cmd('network virtual-appliance reimage -g {rg} --network-virtual-appliance-name {nva_name} --subscription {subscription} --instance-ids {instance_id}')

        # Wait for the reimage operation to complete and check provisioning state
        provisioning_state = self.cmd('network virtual-appliance show -g {rg} -n {nva_name}').get_output_in_json()['provisioningState']
        retry_count = 0
        while provisioning_state != 'Succeeded':
            if retry_count == 20:
                raise Exception(f"Reimage operation did not complete successfully. Last known provisioningState: {provisioning_state}")
            retry_count += 1
            sleep(60)
            provisioning_state = self.cmd('network virtual-appliance show -g {rg} -n {nva_name}').get_output_in_json()['provisioningState']

        # Ensure that the provisioning state is 'Succeeded' after reimaging
        self.cmd('network virtual-appliance show -g {rg} -n {nva_name}',
                 checks=[
                     self.check('provisioningState', 'Succeeded')
                 ])

class NetworkVirtualApplianceVnetScenarioTest(ScenarioTest):

    @AllowLargeResponse()
    @ResourceGroupPreparer(location='eastus2euap', name_prefix='test_nva_vnet')
    def test_network_virtual_appliance_vnet_interface_config(self, resource_group):
        from time import sleep

        def _get_request_id(ex: Exception) -> str:
            try:
                headers = getattr(getattr(ex, 'response', None), 'headers', {}) or {}
                return headers.get('x-ms-request-id', 'N/A')
            except Exception:
                return 'N/A'

        def _is_transient_update_error(ex: Exception) -> bool:
            msg = str(ex)
            return ('NvaOperationNotAllowed' in msg) or ('nvaoperationnotallowed' in msg.lower())

        # -------- (0) args --------
        self.kwargs.update({
            'rg': resource_group,
            'vnet': 'cli-nva-vnet',
            'addrSpace': '10.10.0.0/16',

            'subnetPriv': 'ApplianceSubnet',  # nic0
            'privPrefix': '10.10.1.0/24',

            'subnetPub': 'ApplianceSubnetPublic',  # nic1
            'pubPrefix': '10.10.2.0/24',

            'name': 'cli-virtual-appliance-vnet',
            'vendor': 'barracudasdwanrelease',
            'version': 'latest',
            'asn': '10000',
            'scale': '10',
            'asnUpdated': '20000',
        })

        # ------- (1) network dependencies -------
        self.cmd(
            'network vnet create '
            '-g {rg} -n {vnet} -l eastus2euap '
            '--address-prefixes {addrSpace} '
            '--subnet-name {subnetPriv} --subnet-prefix {privPrefix}',
            checks=[self.check('newVNet.subnets[0].name', '{subnetPriv}')]
        )
        self.cmd(
            'network vnet subnet create '
            '-g {rg} --vnet-name {vnet} -n {subnetPub} '
            '--address-prefixes {pubPrefix}',
            checks=[self.check('name', '{subnetPub}')]
        )

        vnet = self.cmd('network vnet show -g {rg} -n {vnet}').get_output_in_json()
        sub_priv_id = next(s['id'] for s in vnet['subnets'] if s['name'] == self.kwargs['subnetPriv'])
        sub_pub_id = next(s['id'] for s in vnet['subnets'] if s['name'] == self.kwargs['subnetPub'])

        # ------- (2) init interface config -------
        iface_init = (
                         "[{name:'nic0',subnet:{id:'%s'},type:['PrivateNic']},"
                         "{name:'nic1',subnet:{id:'%s'},type:['PublicNic']}]"
                     ) % (sub_priv_id, sub_pub_id)
        self.kwargs.update({'iface_init': iface_init})

        # ------- (3) create -------
        self.cmd(
            "network virtual-appliance create "
            "-n {name} -g {rg} "
            "--vendor {vendor} --scale-unit {scale} -v {version} --asn {asn} "
            "--interface-configs '{iface_init}'",
            checks=[
                self.check('name', '{name}'),
                self.check('length(nvaInterfaceConfigurations)', 2),
                self.check('virtualApplianceAsn', '{asn}')
            ]
        )

        # ------- (3.1) list -------
        self.cmd(
            'network virtual-appliance list -g {rg}',
            checks=[self.check('length(@)', 1), self.check('[0].name', '{name}')]
        )

        # ------- (4) loop until succeeded --------
        retry_count = 0
        while True:
            show = self.cmd('network virtual-appliance show -g {rg} -n {name}').get_output_in_json()
            state = show.get('provisioningState')

            if state == 'Succeeded':
                break
            retry_count += 1
            if retry_count >= 20:
                raise Exception(f'Operation not complete: provisioningState={state}, retry_count={retry_count}')
            sleep(60)

        # -------- (5) wait 15 min --------
        sleep(15 * 60)

        max_retries = 5
        attempt = 0
        while True:
            try:
                self.cmd(
                    'network virtual-appliance update -n {name} -g {rg} --asn {asnUpdated}',
                    checks=[
                        self.check('name', '{name}'),
                        self.check('virtualApplianceAsn', '{asnUpdated}'),
                        self.check('length(nvaInterfaceConfigurations)', 2),
                        self.check('nvaInterfaceConfigurations[0].name', 'nic0'),
                        self.check('nvaInterfaceConfigurations[1].name', 'nic1'),
                    ]
                )
                break
            except Exception as ex:
                attempt += 1
                req_id = _get_request_id(ex)
                if attempt > max_retries or not _is_transient_update_error(ex):
                    raise Exception(
                        f'UPDATE failed after {attempt} attempt(s). '
                        f'x-ms-request-id={req_id}. Error={ex}'
                    )
                sleep(10 * 60)

        # ------- (6) verify show -------
        show = self.cmd('network virtual-appliance show -n {name} -g {rg}').get_output_in_json()
        iface_count = len(show['nvaInterfaceConfigurations'])
        expected_nics = len(show['virtualApplianceNics'])

        self.cmd(
            'network virtual-appliance show -n {name} -g {rg}',
            checks=[
                self.check('name', '{name}'),
                self.check('virtualApplianceAsn', '{asnUpdated}'),
                self.check('length(nvaInterfaceConfigurations)', iface_count),
                self.check('length(virtualApplianceNics)', expected_nics)
            ]
        )

        # ------- (7) delete with retries -------
        retry_count = 0
        while True:
            show = self.cmd('network virtual-appliance show -n {name} -g {rg}').get_output_in_json()
            state = show.get('provisioningState')
            if state in ('Succeeded', 'Failed'):
                break
            retry_count += 1
            if retry_count >= 10:
                print(f'WARN: provisioningState={state}, proceed to delete anyway.')
                break
            sleep(60)

        def _is_transient_nva_error(ex: Exception) -> bool:
            msg = str(ex).lower()
            return ('nvaoperationnotallowed' in msg) or ('nvaoperationfailed' in msg)

        max_del_retries = 6
        attempt = 0
        while True:
            try:
                self.cmd('network virtual-appliance delete -n {name} -g {rg} -y')
                break
            except Exception as ex:
                attempt += 1
                if attempt > max_del_retries or not _is_transient_nva_error(ex):
                    print(f'WARN: NVA delete failed ({ex}); fallback to --no-wait and RG delete.')
                    try:
                        self.cmd('network virtual-appliance delete -n {name} -g {rg} -y --no-wait')
                    except Exception as ex2:
                        print(f'WARN: async NVA delete also failed: {ex2}')
                    try:
                        self.cmd('group delete --name {rg} --yes --no-wait')
                    except Exception as ex3:
                        print(f'WARN: RG delete initiation failed: {ex3}')
                    break
                print(
                    f'INFO: NVA delete transient failure (attempt {attempt}/{max_del_retries}). Sleep 10 minutes then retry...')
                sleep(10 * 60)

        # ------- (8) verify deletion -------
        self.cmd('network virtual-appliance show -n {name} -g {rg}', expect_failure=True)


class NetworkExtendedLocation(ScenarioTest):
    @ResourceGroupPreparer(name_prefix='test_network_lb_edge_zone', location='eastus2euap')
    def test_network_lb_edge_zone(self, resource_group):

        self.kwargs.update({
            'lb': 'lb',
            'lb1': 'lb1',
            'sku': 'standard',
            'ip': 'pubip1',
            'edge_name': 'microsoftrrdclab1'
        })

        self.cmd('network lb create -g {rg} -n {lb} --sku {sku} --public-ip-address {ip} --edge-zone {edge_name}')
        self.cmd('network lb show -g {rg} -n {lb}', checks=self.check('extendedLocation.name', '{edge_name}'))

        self.cmd('network lb create -g {rg} -n {lb1} --vnet-name vnet1 --subnet subnet1 --edge-zone {edge_name}')

    @ResourceGroupPreparer(name_prefix='test_network_nic_edge_zone', location='eastus2euap')
    def test_network_nic_edge_zone(self, resource_group):

        self.kwargs.update({
            'vnet': 'clitestvnet',
            'nic': 'clitestnic',
            'rg': resource_group,
            'edge_name': 'microsoftdclabs1'
        })
        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name subnet1 --edge-zone {edge_name}',
                 checks=self.check('newVNet.extendedLocation.name', '{edge_name}'))
        self.cmd('network nic create -g {rg} -n {nic} --subnet subnet1 --vnet-name {vnet} --edge-zone {edge_name}',
                 checks=self.check('NewNIC.extendedLocation.name', '{edge_name}'))

    @ResourceGroupPreparer(name_prefix='test_network_public_ip_edge_zone', location='eastus2euap')
    def test_network_public_ip_edge_zone(self, resource_group):

        self.kwargs.update({
            'rg': resource_group,
            'ip1': 'pubip1',
            'edge_name': 'microsoftrrdclab1'
        })

        self.cmd('network public-ip create -g {rg} -n {ip1} --edge-zone {edge_name} --sku Standard',
                 checks=self.check('publicIp.extendedLocation.name', '{edge_name}'))

    @ResourceGroupPreparer(name_prefix='test_network_public_ip_prefix_edge_zone', location='eastus2euap')
    def test_network_public_ip_prefix_edge_zone(self, resource_group):

        self.kwargs.update({
            'rg': resource_group,
            'ip1': 'pubip1-prefix',
            'edge_name': 'microsoftrrdclab1'
        })

        self.cmd('network public-ip prefix create -g {rg} -n {ip1} --length 30 --edge-zone {edge_name}',
                 checks=self.check('extendedLocation.name', '{edge_name}'))

    @ResourceGroupPreparer(name_prefix='test_network_public_ip_prefix_with_tier', location='eastus2euap')
    def test_network_public_ip_prefix_with_tier(self, resource_group):
        self.kwargs.update({
            'prefix1': self.create_random_name('prefix', 15),
            'prefix2': self.create_random_name('prefix', 15),
        })

        self.cmd('network public-ip prefix create -g {rg} -n {prefix1} --length 28 --tier regional',
                 checks=self.check('sku.tier', 'Regional'))
        self.cmd('network public-ip prefix create -g {rg} -n {prefix2} --length 28 --tier global',
                 checks=self.check('sku.tier', 'Global'))

    # @unittest.skip('wait for service ready')
    @ResourceGroupPreparer(name_prefix='test_network_vnet_gateway_edge_zone', location='southeastasia')
    def test_network_vnet_gateway_edge_zone(self, resource_group):

        self.kwargs.update({
            'rg': resource_group,
            'ip1': 'pubip1',
            'vnet': 'vnet',
            'edge_name': 'microsoftrrdclab1'
        })
        self.cmd('network public-ip create -g {rg} -n {ip1}')
        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name GatewaySubnet')
        self.cmd('network vnet-gateway create -g {rg} -n vnet-gateway --vnet {vnet} --public-ip-address {ip1} '
                 '--edge-zone {edge_name}',
                 checks=self.check('vnetGateway.extendedLocation.name', '{edge_name}'))

    @ResourceGroupPreparer(name_prefix='test_network_vnet_gateway_local_gateway', location='eastus2euap')
    def test_network_vnet_gateway_local_gateway(self, resource_group):

        self.kwargs.update({
            'rg': resource_group,
            'vnet': 'vnet',
            'gateway_type': 'LocalGateway',
            'edge_name': 'microsoftrrdclab3',
        })
        self.cmd('az network vnet create -g {rg} -n {vnet} --location eastus2euap --address-prefix 10.30.0.0/16 --edge-zone {edge_name}')
        self.kwargs['edge_zone_vnet_id'] = self.cmd('network vnet show -g {rg} -n {vnet}').get_output_in_json()['id']
        self.cmd('network vnet-gateway create -g {rg} -n vnet-gateway --vnet {vnet} --gateway-type {gateway_type} --edge-zone {edge_name} '
                 '--edge-zone-vnet-id {edge_zone_vnet_id}',
                 checks=self.check('vnetGateway.vNetExtendedLocationResourceId', '{edge_zone_vnet_id}'))

    @ResourceGroupPreparer(name_prefix='test_network_vnet_gateway_with_enable_private_ip_address', location='eastus')
    def test_network_vnet_gateway_with_enable_private_ip_address(self, resource_group):
        self.kwargs.update({
            'rg': resource_group,
            'ip': self.create_random_name('ip-', 10),
            'vnet': self.create_random_name('vnet-', 10),
            'vnet_gateway': self.create_random_name('vg-', 10),
        })

        self.cmd('network vnet create -g {rg} -n {vnet} -l eastus --address-prefix 10.1.0.0/16 --subnet-name Frontend --subnet-prefix 10.1.0.0/24')
        self.cmd('network vnet subnet create -g {rg} --vnet-name {vnet} -n GatewaySubnet --address-prefix 10.1.255.0/27 --default-outbound false')
        self.cmd('network public-ip create -g {rg} -n {ip}')
        self.cmd('network vnet-gateway create -g {rg} -n {vnet_gateway} --vnet {vnet} --public-ip-address {ip} --gateway-type Vpn --sku VpnGw2 --vpn-gateway-generation Generation2 --enable-private-ip true -l eastus --no-wait')
        self.cmd('network vnet-gateway show -g {rg} -n {vnet_gateway}', checks=self.check("enablePrivateIpAddress", True))
        self.cmd('network vnet-gateway wait -g {rg} -n {vnet_gateway} --created')
        self.cmd('network vnet-gateway update -g {rg} -n {vnet_gateway} --enable-private-ip false')
        self.cmd('network vnet-gateway show -g {rg} -n {vnet_gateway}', checks=self.check("enablePrivateIpAddress", False))

    @ResourceGroupPreparer(name_prefix='test_network_private_endpoint_edge_zone', location='eastus2euap')
    def test_network_private_endpoint_edge_zone(self, resource_group):

        self.kwargs.update({
            'rg': resource_group,
            'lb': 'lb',
            'vnet': 'vnet',
            'edge_name': 'microsoftdclabs1',
            'subnet1': 'subnet1',
            'subnet2': 'subnet2',
        })
        self.cmd('network lb create -g {rg} -n {lb} --public-ip-address ip --sku Standard')
        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name {subnet1} --edge-zone {edge_name}')
        self.cmd('network vnet subnet update -g {rg} -n {subnet1} --vnet-name {vnet} '
                 '--disable-private-link-service-network-policies')
        self.cmd('network vnet subnet create -g {rg} -n {subnet2} --vnet-name {vnet} '
                 '--address-prefixes 10.0.2.0/24 --default-outbound false')
        self.cmd('network vnet subnet update -g {rg} -n {subnet2} --vnet-name {vnet} '
                 '--disable-private-endpoint-network-policies')

        pls = self.cmd('network private-link-service create -g {rg} -n pls --vnet-name {vnet} --subnet {subnet1} '
                       '--lb-name {lb} --lb-frontend-ip-configs LoadBalancerFrontEnd --edge-zone {edge_name}',
                       checks=self.check('extendedLocation.name', '{edge_name}')).get_output_in_json()
        self.kwargs['pls_id'] = pls['id']
        self.cmd('network private-endpoint create -g {rg} -n pe --vnet-name {vnet} --subnet {subnet2} '
                 '--private-connection-resource-id {pls_id} --connection-name cn --edge-zone {edge_name}',
                 checks=self.check('extendedLocation.name', '{edge_name}'))


class NetworkLoadBalancerWithSkuGateway(ScenarioTest):

    @ResourceGroupPreparer(name_prefix='test_network_lb_tunnel_interface', location='eastus')
    def test_network_lb_tunnel_interface(self, resource_group):

        self.kwargs.update({
            'rg': resource_group,
            'lb': 'lb',
            'sku': 'Gateway',
            'vnet': 'vnet',
            'subnet': 'subnet',
            'bap': 'backend-address-pool-name',
            'type': 'External',
            'type1': 'Internal',
            'protocol': 'vxlan',
            'identifier': '950',
            'identifier1': '960',
        })

        self.cmd('network lb create -g {rg} -n {lb} --sku {sku} --vnet-name {vnet} --subnet {subnet}')
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n {bap} --vnet {vnet}')

        # default
        self.cmd('network lb address-pool tunnel-interface add -g {rg} --lb-name {lb} --address-pool {bap} '
                 '--type {type} --protocol {protocol} --identifier {identifier} --port 15000',
                 checks=self.check('length(tunnelInterfaces)', 2))
        self.cmd('network lb address-pool tunnel-interface list -g {rg} --lb-name {lb} --address-pool {bap}',
                 checks=self.check('length(@)', 2))
        self.cmd('network lb address-pool tunnel-interface remove -g {rg} --lb-name {lb} --address-pool {bap} '
                 '--index 0')
        self.cmd('network lb address-pool tunnel-interface update -g {rg} --lb-name {lb} --address-pool {bap} '
                 '--type {type1} --protocol {protocol} --identifier {identifier1} --port 10000 --index 0',
                 checks=self.check('tunnelInterfaces[0].type', '{type1}'))

    @ResourceGroupPreparer(name_prefix='test_network_lb_front_ip', location='westus')
    def test_network_lb_front_ip(self, resource_group):
        self.kwargs.update({
            'rg': resource_group,
            'lb': 'lb',
            'lb1': 'lb1',
            'vnet': 'vnet',
            'subnet': 'subnet',
            'ip': 'public-ip',
            'ip1': 'public-ip1',
            'fip': 'load-balancer-frontend-end',
            'prefix': 'prefix',
        })

        self.cmd('network lb create -g {rg} -n {lb} --sku Standard --public-ip-address {ip}')
        self.cmd('network lb create -g {rg} -n {lb1} --sku Gateway --vnet-name {vnet} --subnet {subnet} ')
        self.cmd('network public-ip create -g {rg} -n {ip1} --sku standard')
        self.cmd('network lb frontend-ip create -g {rg} --lb-name {lb} -n {fip} --public-ip-address {ip1}',
                 checks=self.not_exists('gatewayLoadBalancer'))
        result = self.cmd('network lb frontend-ip create -g {rg} --lb-name {lb1} -n {fip} '
                          '--vnet-name {vnet} --subnet {subnet}').get_output_in_json()
        # test --gateway-lb
        self.kwargs['id'] = result['id']
        self.cmd('network lb frontend-ip update -g {rg} --lb-name {lb} -n {fip} --gateway-lb {id}',
                 checks=self.exists('gatewayLoadBalancer'))

        self.cmd("network lb frontend-ip update -g {rg} --lb-name {lb} -n {fip} --gateway-lb null",
                 checks=self.check('gatewayLoadBalancer', None))
        self.cmd("network lb frontend-ip list -g {rg} --lb-name {lb}",
                 checks=self.check('length(@)', 2))
        self.cmd("network lb frontend-ip delete -g {rg} --lb-name {lb} -n LoadBalancerFrontEnd")
        self.cmd("network lb frontend-ip list -g {rg} --lb-name {lb}",
                 checks=self.check('length(@)', 1))
        self.cmd("network lb frontend-ip update -g {rg} --lb-name {lb} -n {fip} --public-ip-address null "
                 "--vnet-name {vnet} --subnet {subnet}",
                 checks=[
                     self.check('publicIPAddress', None),
                     self.check("subnet.id.contains(@, '{subnet}')", True),
                     self.check("subnet.id.contains(@, '{vnet}')", True)
                 ])
        self.cmd('network public-ip prefix create -g {rg} -n {prefix} --length 30')
        self.cmd("network lb frontend-ip update -g {rg} --lb-name {lb} -n {fip} --subnet null "
                 "--public-ip-prefix {prefix}",
                 checks=[
                     self.check("publicIPPrefix.id.contains(@, '{prefix}')", True),
                     self.check("subnet", None),
                 ])
        self.cmd("network lb frontend-ip update -g {rg} --lb-name {lb} -n {fip} --public-ip-address {ip1} "
                 "--public-ip-prefix null",
                 checks=[
                     self.check("publicIPAddress.id.contains(@, '{ip1}')", True),
                     self.check("publicIPPrefix", None),
                 ])

    @ResourceGroupPreparer(name_prefix='test_network_nic_front_ip', location='eastus2euap')
    def test_network_nic_front_ip(self, resource_group):

        self.kwargs.update({
            'rg': resource_group,
            'lb': 'lb',
            'vnet': 'vnet',
            'vnet1': 'vnet1',
            'subnet': 'subnet',
            'subnet1': 'subnet1',
            'ip': 'public-ip',
            'ip1': 'public-ip1',
            'fip': 'load-balancer-frontend-end',
            'nic': 'nic-name',
            'nip': 'nic-ip-config-name',
        })

        self.cmd('network public-ip create -g {rg} -n {ip} --sku standard')
        self.cmd('network public-ip create -g {rg} -n {ip1} --sku standard')
        self.cmd('network vnet create -g {rg} -n {vnet} --subnet-name {subnet}')
        self.cmd('network nic create -g {rg} -n {nic} --public-ip-address {ip} --vnet-name {vnet} --subnet {subnet}')
        self.cmd('network lb create -g {rg} -n {lb} --sku Gateway --vnet-name {vnet1} --subnet {subnet1} ')
        result = self.cmd('network lb frontend-ip create -g {rg} --lb-name {lb} -n {fip} '
                          '--vnet-name {vnet1} --subnet {subnet1}').get_output_in_json()
        self.kwargs['id'] = result['id']
        self.cmd('network nic ip-config create -g {rg} --nic-name {nic} -n {nip} --make-primary '
                 '--public-ip-address {ip1}',
                 checks=self.not_exists('gatewayLoadBalancer'))

        # test --gateway-lb
        self.cmd('network nic ip-config update -g {rg} --nic-name {nic} -n {nip} --gateway-lb {id}',
                 checks=self.exists('gatewayLoadBalancer'))

    @ResourceGroupPreparer(name_prefix='test_network_lb_rule_backend_address_pools', location='eastus2euap')
    def test_network_lb_rule_backend_address_pools(self, resource_group):

        self.kwargs.update({
            'rg': resource_group,
            'lb': 'lb',
            'fip': 'LoadBalancerFrontEnd',
            'bap1': 'address-pool-name1',
            'bap2': 'address-pool-name2',
            'bap3': 'address-pool-name3',
            'type': 'External',
            'protocol': 'vxlan',
            'identifier': '901',
            'identifier1': '902',
            'port': '10700',
            'fport': '0',
            'bport': '0'
        })

        self.cmd('network lb create -g {rg} -n {lb} --sku Gateway --vnet-name vnet --subnet subnet')
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n {bap1}')
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n {bap2}')
        self.cmd('network lb address-pool create -g {rg} --lb-name {lb} -n {bap3}')
        self.cmd('network lb address-pool tunnel-interface add -g {rg} --lb-name {lb} --address-pool {bap1} --type {type}  --protocol {protocol} --identifier {identifier}')
        self.cmd('network lb address-pool tunnel-interface update -g {rg} --lb-name {lb} --address-pool {bap2} --type {type} --index 0')
        self.cmd('network lb address-pool tunnel-interface update -g {rg} --lb-name {lb} --address-pool {bap3} --port {port} --identifier {identifier1} --index 0')

        # test --backend-pool-name
        self.cmd('network lb rule create -g {rg} --lb-name {lb} -n rule1 --frontend-ip-name {fip} '
                 '--frontend-port {fport}  --protocol All --backend-port {bport} --backend-pool-name {bap1} ',
                 checks=[self.exists('backendAddressPool'),
                         self.check('length(backendAddressPools)', 1)])
        self.cmd('network lb rule delete --lb-name {lb} -g {rg} -n rule1')
        # test --backend-pools-name
        self.cmd('network lb rule create -g {rg} --lb-name {lb} -n rule2 --frontend-ip-name {fip} '
                 '--frontend-port {fport} --backend-pools-name {bap3} {bap2} --protocol All  --backend-port {bport}',
                 checks=[self.not_exists('backendAddressPool'),
                         self.check('length(backendAddressPools)', 2)])
        self.cmd('network lb rule update -g {rg} --lb-name {lb} -n rule2 --frontend-ip-name {fip} '
                 '--backend-pools-name {bap1} ',
                 checks=[self.check('length(backendAddressPools)', 1)])

class NetworkVnetGatewayFailoverAPIsTest(ScenarioTest):

    @live_only()
    def test_start_site_failover_test(self): # live_only as the express route is extremely expensive, contact service team for an available ER
        resource_group = "shubhati_failover"  
        vnet_gateway_name = "shubhati_failoverGw"
        peering_location = "London2"

        self.kwargs.update({
            'rg': resource_group,
            'vnet_gw': vnet_gateway_name,
            'peering_loc': peering_location
        })

        # Run the command
        result = self.cmd(
            'network vnet-gateway start-site-failover-test '
            '-g {rg} --virtual-network-gateway-name {vnet_gw} --peering-location {peering_loc}'
        ).get_output_in_json()

        # Validate that result is a string (per _schema_on_200 = AAZStrType())
        self.assertIsInstance(result, dict)

    @live_only()
    def test_stop_site_failover_test(self): # live_only as the express route is extremely expensive, contact service team for an available ER
        import time

        time.sleep(2 * 60)  # 120 seconds To wait for sometime before stopping the test failover
        resource_group = "shubhati_failover"
        vnet_gateway_name = "shubhati_failoverGw"
        peering_location = "London2"
        was_simulation_successful = True

        # Construct failover test connection details
        failover_details = [
            {
                "failover-connection-name": "failoverGR",
                "failover-location": "Amsterdam",
                "is-verified": True
            }
        ]

        # Convert details list to CLI argument format
        details_arg = "[" + ",".join(
            "{{failover-connection-name:{},failover-location:{},is-verified:{}}}".format(
                d["failover-connection-name"],
                d["failover-location"],
                str(d["is-verified"]).lower()
            ) for d in failover_details
        ) + "]"

        self.kwargs.update({
            'rg': resource_group,
            'vnet_gw': vnet_gateway_name,
            'peering_loc': peering_location,
            'was_successful': was_simulation_successful,
            'details_arg': details_arg
        })

        # Run the command
        result = self.cmd(
            'network vnet-gateway stop-site-failover-test '
            '-g {rg} --virtual-network-gateway-name {vnet_gw} '
            '--peering-location {peering_loc} '
            '--was-simulation-successful {was_successful} '
            '--details \'{details_arg}\''
        ).get_output_in_json()

        # Validate
        self.assertTrue(isinstance(result, (str, dict)))

class NetworkVnetGatewayRoutesAndResiliencyInfoScenarioTest(ScenarioTest):

    @live_only()
    @ResourceGroupPreparer(name_prefix='test_vnet_gw_routes_resiliency_info', location='eastus2euap')
    @AllowLargeResponse(size_kb=9999)
    def test_network_vnet_gateway_get_routes_and_resiliency_information(self, resource_group):
        from time import sleep

        subscription_id = self.get_subscription_id()

        self.kwargs.update({
            'rg': resource_group,
            'gw': self.create_random_name('ergw', 20),
            'vnet': 'vnet1',
            'subnet': 'GatewaySubnet',
            'pip': 'pip1',
            'subscription': subscription_id
        })

        # Create Virtual Network with GatewaySubnet
        self.cmd('network vnet create -g {rg} -n {vnet} --address-prefix 10.0.0.0/16 '
                 '--subnet-name {subnet} --subnet-prefix 10.0.0.0/24', checks=[
            self.check('newVNet.name', '{vnet}')
        ])

        # Create Public IP
        self.cmd('network public-ip create -g {rg} -n {pip} --sku Standard', checks=[
            self.check('publicIp.name', '{pip}')
        ])

        # Create ExpressRoute Virtual Network Gateway
        self.cmd('network vnet-gateway create -g {rg} -n {gw} --vnet {vnet} '
                 '--public-ip-addresses {pip} --gateway-type ExpressRoute '
                 '--sku ErGw1AZ --no-wait')

        # Wait until the ExpressRoute gateway is provisioned
        self.cmd('network vnet-gateway wait -g {rg} -n {gw} --created')

        # Retry loop to verify provisioning state
        provisioning_state = self.cmd('network vnet-gateway show -g {rg} -n {gw}').get_output_in_json()['provisioningState']
        retry_count = 0
        while provisioning_state != 'Succeeded':
            if retry_count == 20:
                raise Exception(f"ExpressRoute Gateway provisioning failed. Last known state: {provisioning_state}")
            retry_count += 1
            sleep(60)
            provisioning_state = self.cmd('network vnet-gateway show -g {rg} -n {gw}').get_output_in_json()['provisioningState']

        # ---------------------------
        # Get Routes Information
        # ---------------------------
        self.cmd('network vnet-gateway get-routes-information -g {rg} --name {gw} --attempt-refresh true', checks=[
            self.check('type(@)', 'object'),
            self.check('length(lastComputedTime)', 24),  # Format: '8/22/2025 5:57:28 PM UTC' = 24 characters
            self.check('length(nextEligibleComputeTime)', 24),
            self.check('length(routeSetVersion)', 36),  # UUIDs are always 36 characters
            self.check('type(routeSets)', 'array'),
            self.check('type(circuitsMetadataMap)', 'object')
        ])

        # ---------------------------
        # Get Resiliency Information
        # ---------------------------
        self.cmd('network vnet-gateway get-resiliency-information -g {rg} --name {gw} --attempt-refresh true', checks=[
            self.check('type(@)', 'object'),
            self.check('length(overallScore)', 2),
            self.check('length(scoreChange)', 3),
            self.check('length(minScoreFromRecommendations)', 2),
            self.check('length(maxScoreFromRecommendations)', 3),
            self.check('length(lastComputedTime)', 24),
            self.check('length(nextEligibleComputeTime)', 24),
            self.check('type(components)', 'array')
        ])

class NetworkExpressRouteGatewayFailoverSimulationScenarioTest(ScenarioTest):
    @live_only()
    def test_network_express_route_gateway_failover(self): # live_only as the express route is extremely expensive, contact service team for an available ER
        resource_group = "bhavana-vwan-failover"  
        er_gateway_name = "422dcfc236aa44f6838f556330b628e1-centraluseuap-er-gw"
        peering_location = "DataPathLocation1"
        test_guid = "fb5c66a6-6852-49d9-bf56-fc3e8d2f2a3b"
        was_simulation_successful = True

        self.kwargs.update({
            'rg': resource_group,
            'er_gw': er_gateway_name,
            'peering_loc': peering_location
        })

        # Run the command
        result = self.cmd(
            'network express-route gateway start-site-failover-test '
            '--resource-group {rg} --name {er_gw} --peering-location {peering_loc}'
        ).get_output_in_json()

        # Validate that result is a string (per _schema_on_200 = AAZStrType())
        self.assertIsInstance(result, dict)
        
        import time
        time.sleep(2 * 60)  # 120 seconds To wait for sometime before stopping the test failover 

        # Construct failover test connection details
        failover_details = [
            {
                "failover-connection-name": "ExRConnection-centraluseuap-1772183583607",
                "failover-location": "DataPathLocation1",
                "is-verified": True
            }
        ]

        # Convert details list to CLI argument format
        details_arg = "[" + ",".join(
            "{{failover-connection-name:{},failover-location:{},is-verified:{}}}".format(
                d["failover-connection-name"],
                d["failover-location"],
                str(d["is-verified"]).lower()
            ) for d in failover_details
        ) + "]"

        self.kwargs.update({
            'rg': resource_group,
            'er_gw': er_gateway_name,
            'peering_loc': peering_location,
            'was_successful': was_simulation_successful,
            'details_arg': details_arg,
            'test_guid': test_guid
        })

        # Run the command
        result = self.cmd(
            'network express-route gateway stop-site-failover-test '
            '--resource-group {rg} --name {er_gw} '
            '--peering-location {peering_loc} '
            '--simulation-successful {was_successful} '
            '--details \'{details_arg}\''
        ).get_output_in_json()

        # Validate
        self.assertTrue(isinstance(result, (str, dict)))

        # Run all tests detail command to validate the stop operation
        tests_link_latest = self.cmd(
            'network express-route gateway get-failover-all-tests-detail '
            '--resource-group {rg} --name {er_gw} '
            '--fetch-latest True --type SingleSiteFailover'
        ).get_output_in_json()

        self.assertIsInstance(tests_link_latest, dict)

        #
        single_test_result = self.cmd(
                'network express-route gateway get-failover-single-test-detail '
                '--resource-group {rg} --name {er_gw} '
                '--failover-test-id {test_guid} '
                '--peering-location {peering_loc} '
            ).get_output_in_json()

        # Validate response structure
        self.assertIsInstance(single_test_result, dict)


class NetworkExpressRouteGatewayRoutesResiliencyScenarioTest(ScenarioTest):

    @live_only()  # live_only as express route gateways require expensive resources
    @ResourceGroupPreparer(name_prefix='test_express_route_gateway_routes_resiliency', location='eastus')
    @AllowLargeResponse(size_kb=9999)
    def test_network_express_route_gateway_routes_and_resiliency(self, resource_group):
        """
        Test Express Route Gateway routes and resiliency information operations:
        - Get routes information
        - Get resiliency information
        """
        from time import sleep

        resource_group = "bhavana-vwan-failover"  
        er_gateway_name = "422dcfc236aa44f6838f556330b628e1-centraluseuap-er-gw"
        attempt_refresh = True

        self.kwargs.update({
            'rg': resource_group,
            'er_gw': er_gateway_name,
            'attempt_refresh': attempt_refresh
        })

        # Test 1: Get Routes Information
        routes_result = self.cmd(
            'network express-route gateway get-routes-information '
            '--resource-group {rg} --name {er_gw} --attempt-refresh {attempt_refresh}'
        ).get_output_in_json()

        # Validate routes information response structure
        self.assertIsInstance(routes_result, dict)
        self.assertIn('routeSetVersion', routes_result)
        self.assertIn('lastComputedTime', routes_result)
        self.assertIn('nextEligibleComputeTime', routes_result)
        if 'routeSets' in routes_result:
            self.assertIsInstance(routes_result['routeSets'], list)
        if 'circuitsMetadataMap' in routes_result:
            self.assertIsInstance(routes_result['circuitsMetadataMap'], dict)

        # Test 2: Get Resiliency Information
        resiliency_result = self.cmd(
            'network express-route gateway get-resiliency-information '
            '--resource-group {rg} --name {er_gw} --attempt-refresh {attempt_refresh}'
        ).get_output_in_json()

        # Validate resiliency information response structure
        self.assertIsInstance(resiliency_result, dict)
        self.assertIn('overallScore', resiliency_result)
        self.assertIn('lastComputedTime', resiliency_result)
        self.assertIn('nextEligibleComputeTime', resiliency_result)
        if 'components' in resiliency_result:
            self.assertIsInstance(resiliency_result['components'], list)
            if len(resiliency_result['components']) > 0:
                component = resiliency_result['components'][0]
                self.assertIn('name', component)
                self.assertIn('currentScore', component)
                if 'recommendations' in component:
                    self.assertIsInstance(component['recommendations'], list)


class NetworkVirtualNetworkApplianceScenario(ScenarioTest):
    @ResourceGroupPreparer(name_prefix='test_vna', location='eastus')
    def test_network_virtual_network_appliance(self, resource_group):
        self.kwargs.update({
            'vnet1': 'vnet1',
            'vnet2': 'vnet2',
            'vnet_address': '10.10.0.0/16',
            'subnet': 'VirtualNetworkApplianceSubnet',
            'subnet_address': '10.10.0.0/24',
            'vna1': 'vna1',
            'vna2': 'vna2',
            'tag1': 'tag1',
            'tag2': 'tag2',
        })

        # Create vnet, subnet for first vna
        self.cmd('network vnet create -g {rg} -n {vnet1} --address-prefixes {vnet_address}')

        self.kwargs['subnet1_id'] = self.cmd('network vnet subnet create -g {rg} -n {subnet} --vnet-name {vnet1} --address-prefix {subnet_address} --default-outbound false --query id').get_output_in_json()

        # Create first vna
        self.cmd('network virtual-network-appliance create -g {rg} -n {vna1} --bandwidth-in-gbps 50 --subnet \"{{id:{subnet1_id}}}\" --tags \"{{name:{tag1}}}\"')

        self.cmd('network virtual-network-appliance show -g {rg} -n {vna1}', checks=[
            self.check('tags.name', '{tag1}'),
            self.check('subnet.id', '{subnet1_id}'),
            self.check('bandwidthInGbps', 50),
        ])

        self.cmd('network virtual-network-appliance update -g {rg} -n {vna1} --tags \"{{name:{tag2}}}\"', checks=[
            self.check('tags.name', '{tag2}'),
        ])

        self.cmd('network virtual-network-appliance list -g {rg}', checks=[
            self.check('length(@)', 1)
        ])

        # Create vnet, subnet for second vna
        self.cmd('network vnet create -g {rg} -n {vnet2} --address-prefixes {vnet_address}')

        self.kwargs['subnet2_id'] = self.cmd('network vnet subnet create -g {rg} -n {subnet} --vnet-name {vnet2} --address-prefix {subnet_address} --default-outbound false --query id').get_output_in_json()

        # Create second vna
        vna2_id = self.cmd('network virtual-network-appliance create -g {rg} -n {vna2} --bandwidth-in-gbps 50 --subnet \"{{id:{subnet2_id}}}\" --query id').get_output_in_json()

        self.cmd('network virtual-network-appliance list -g {rg}', checks=[
            self.check('length(@)', 2)
        ])

        self.cmd('network virtual-network-appliance delete -g {rg} -n {vna1} -y')

        vna_list = self.cmd('network virtual-network-appliance list -g {rg}', checks=[
            self.check('length(@)', 1)
        ]).get_output_in_json()

        self.assertTrue(vna_list[0].get('id') == vna2_id)

    @ResourceGroupPreparer(name_prefix='test_vna_ip_version', location='eastus')
    def test_network_virtual_network_appliance_private_ip_address_version(self, resource_group):
        self.kwargs.update({
            'vnet1': 'vnet-ipv4',
            'vnet2': 'vnet-dualstack',
            'vnet_address': '10.10.0.0/16',
            'subnet': 'VirtualNetworkApplianceSubnet',
            'subnet_address': '10.10.0.0/24',
            'vna_ipv4': 'vna-ipv4',
            'vna_dualstack': 'vna-dualstack',
        })

        # create vnet/subnet for IPv4 vna
        self.cmd('network vnet create -g {rg} -n {vnet1} --address-prefixes {vnet_address}')
        self.kwargs['subnet1_id'] = self.cmd(
            'network vnet subnet create -g {rg} -n {subnet} --vnet-name {vnet1} '
            '--address-prefix {subnet_address} --default-outbound false --query id'
        ).get_output_in_json()

        # create vna with --private-ip-address-version IPv4
        self.cmd(
            'network virtual-network-appliance create -g {rg} -n {vna_ipv4} '
            '--bandwidth-in-gbps 50 --subnet \"{{id:{subnet1_id}}}\" '
            '--private-ip-address-version IPv4'
        )

        self.cmd('network virtual-network-appliance show -g {rg} -n {vna_ipv4}', checks=[
            self.check('privateIPAddressVersion', 'IPv4'),
            self.check('bandwidthInGbps', 50),
        ])

        # create vnet/subnet for DualStack vna (need both IPv4 and IPv6 address spaces)
        self.cmd('network vnet create -g {rg} -n {vnet2} --address-prefixes {vnet_address} fd00:db8::/48')
        self.kwargs['subnet2_id'] = self.cmd(
            'network vnet subnet create -g {rg} -n {subnet} --vnet-name {vnet2} '
            '--address-prefixes {subnet_address} fd00:db8::/64 '
            '--default-outbound false --query id'
        ).get_output_in_json()

        # create vna with --private-ip-address-version DualStack
        self.cmd(
            'network virtual-network-appliance create -g {rg} -n {vna_dualstack} '
            '--bandwidth-in-gbps 100 --subnet \"{{id:{subnet2_id}}}\" '
            '--private-ip-address-version DualStack'
        )

        self.cmd('network virtual-network-appliance show -g {rg} -n {vna_dualstack}', checks=[
            self.check('privateIPAddressVersion', 'DualStack'),
            self.check('bandwidthInGbps', 100),
        ])

        # verify list output includes both fields
        vna_list = self.cmd('network virtual-network-appliance list -g {rg}', checks=[
            self.check('length(@)', 2),
        ]).get_output_in_json()

        for vna in vna_list:
            self.assertIn('privateIPAddressVersion', vna)
            self.assertIn('bandwidthInGbps', vna)


class DdosCustomPolicyScenarioTest(ScenarioTest):
    @ResourceGroupPreparer(name_prefix='test_ddos_cuspol', location='eastus')
    def test_ddos_custom_policy(self, resource_group):
        self.kwargs.update({
            'policy_name': 'policy1',
            'detection_mode': 'TrafficThreshold',
            'detection_rule_name1': 'RuleName1',
            'traffic_type1': 'Tcp',
            'packets_per_second1': '1000000',
            'detection_rule_name2': 'RuleName2',
            'traffic_type2': 'Udp',
            'packets_per_second2': '200000',
            'detection_rule_name3': 'RuleName3',
        })

        self.cmd('network ddos-custom-policy create -g {rg} -n {policy_name} --detection-rule-name {detection_rule_name1} '
                 '--detection-mode {detection_mode} --traffic-type {traffic_type1} --packets-per-second {packets_per_second1}', checks=[
            self.check('length(detectionRules)', 1),
            self.check('detectionRules[0].name', '{detection_rule_name1}'),
            self.check('detectionRules[0].trafficDetectionRule.packetsPerSecond', '{packets_per_second1}'),
            self.check('detectionRules[0].trafficDetectionRule.trafficType', '{traffic_type1}'),
            self.check('name', '{policy_name}'),
        ])

        self.cmd('network ddos-custom-policy show -g {rg} -n {policy_name}', checks=[
            self.check('length(detectionRules)', 1),
            self.check('detectionRules[0].name', '{detection_rule_name1}'),
            self.check('detectionRules[0].trafficDetectionRule.packetsPerSecond', '{packets_per_second1}'),
            self.check('detectionRules[0].trafficDetectionRule.trafficType', '{traffic_type1}'),
            self.check('name', '{policy_name}'),
        ])

        self.cmd('network ddos-custom-policy create -g {rg} -n {policy_name} --detection-rule-name {detection_rule_name2} '
                 '--detection-mode {detection_mode} --traffic-type {traffic_type2} --packets-per-second {packets_per_second2}', checks=[
            self.check('length(detectionRules)', 2),
            self.check('detectionRules[0].name', '{detection_rule_name1}'),
            self.check('detectionRules[0].trafficDetectionRule.packetsPerSecond', '{packets_per_second1}'),
            self.check('detectionRules[0].trafficDetectionRule.trafficType', '{traffic_type1}'),
            self.check('detectionRules[1].name', '{detection_rule_name2}'),
            self.check('detectionRules[1].trafficDetectionRule.packetsPerSecond', '{packets_per_second2}'),
            self.check('detectionRules[1].trafficDetectionRule.trafficType', '{traffic_type2}'),
            self.check('name', '{policy_name}'),
        ])

        self.cmd('network ddos-custom-policy list -g {rg}', checks=[
            self.check('length(@)', 1),
            self.check('[0].name', '{policy_name}'),
        ])

        self.cmd('network ddos-custom-policy update -g {rg} -n {policy_name} --set detectionRules[0].name={detection_rule_name3}', checks=[
            self.check('length(detectionRules)', 2),
            self.check('detectionRules[0].name', '{detection_rule_name3}'),
            self.check('detectionRules[0].trafficDetectionRule.packetsPerSecond', '{packets_per_second1}'),
            self.check('detectionRules[0].trafficDetectionRule.trafficType', '{traffic_type1}'),
            self.check('detectionRules[1].name', '{detection_rule_name2}'),
            self.check('detectionRules[1].trafficDetectionRule.packetsPerSecond', '{packets_per_second2}'),
            self.check('detectionRules[1].trafficDetectionRule.trafficType', '{traffic_type2}'),
        ])

        self.cmd('network ddos-custom-policy update -g {rg} -n {policy_name} --remove detectionRules 0', checks=[
            self.check('length(detectionRules)', 1),
            self.check('detectionRules[0].name', '{detection_rule_name2}'),
            self.check('detectionRules[0].trafficDetectionRule.packetsPerSecond', '{packets_per_second2}'),
            self.check('detectionRules[0].trafficDetectionRule.trafficType', '{traffic_type2}'),
        ])

        self.cmd('network ddos-custom-policy delete -g {rg} -n {policy_name} -y', checks=self.is_empty())

    @ResourceGroupPreparer(name_prefix='test_ddos_cuspol_lb', location='eastus')
    def test_ddos_custom_policy_attach_to_lb_fip(self, resource_group):
        self.kwargs.update({
            'policy_name': 'policy1',
            'pip_name': 'pip1',
            'lb_name': 'lb1',
            'fip_name': 'fip1',
        })

        dcp = self.cmd('network ddos-custom-policy create -g {rg} -n {policy_name} '
                       '--detection-rule-name rule1 --detection-mode TrafficThreshold '
                       '--traffic-type Tcp --packets-per-second 1000000', checks=[
            self.check('name', '{policy_name}'),
        ]).get_output_in_json()
        self.kwargs['dcp_id'] = dcp['id']

        self.cmd('network public-ip create -g {rg} -n {pip_name} --sku Standard --allocation-method Static')
        self.cmd('network lb create -g {rg} -n {lb_name} --sku Standard '
                 '--public-ip-address {pip_name} --frontend-ip-name {fip_name}')

        # Attach the DDoS custom policy to the LB frontend IP configuration
        self.cmd('network lb frontend-ip update -g {rg} --lb-name {lb_name} -n {fip_name} '
                 '--ddos-settings ddos-custom-policy={{id:{dcp_id}}}', checks=[
            self.check('ddosSettings.ddosCustomPolicy.id', '{dcp_id}'),
        ])

        self.cmd('network lb frontend-ip show -g {rg} --lb-name {lb_name} -n {fip_name}', checks=[
            self.check('ddosSettings.ddosCustomPolicy.id', '{dcp_id}'),
        ])

        self.cmd('network lb frontend-ip update -g {rg} --lb-name {lb_name} -n {fip_name} '
                 '--ddos-settings ddos-custom-policy=null', checks=[
            self.check('ddosSettings.ddosCustomPolicy', None),
        ])

        self.cmd('network ddos-custom-policy delete -g {rg} -n {policy_name} -y')


class NetworkPrivateEndpointScenarioTest(ScenarioTest):
    @ResourceGroupPreparer(name_prefix='test_network_private_endpoint_ip_version_type', location='eastus2euap')
    @StorageAccountPreparer(name_prefix='saplr', kind='StorageV2')
    def test_network_private_endpoint_ip_version_type(self, resource_group, storage_account):
        self.kwargs.update({
            'sa': storage_account,
            'rg': resource_group,
            'location': 'eastus2euap',

            'vnet': 'vnetipvt',
            'subnet_pls': 'subnetpls',
            'subnet_pe': 'subnetpe',

            'pe_conn': 'cn',
            'pe_v4': 'peipv4',
            'pe_v6': 'peipv6',
            'pe_ds': 'peds',

            'nic_v4': 'nicv4',
            'nic_v6': 'nicv6',
            'nic_ds': 'nicds',

            # Dual-stack VNet/Subnet prefixes (ULA for IPv6 is fine for private addressing)
            'vnet_ipv4': '10.0.0.0/16',
            'vnet_ipv6': 'fd00:db8:0:0::/56',

            'subnet_pls_ipv4': '10.0.0.0/24',
            'subnet_pe_ipv4': '10.0.1.0/24',
            'subnet_pe_ipv6': 'fd00:db8:0:1::/64',
        })

        # VNet (dual-stack) + PLS subnet
        self.cmd(
            'network vnet create -g {rg} -n {vnet} -l {location} '
            '--address-prefixes {vnet_ipv4} {vnet_ipv6} '
            '--subnet-name {subnet_pls} --subnet-prefixes {subnet_pls_ipv4}'
        )

        # Enable High Scale Private Endpoints (IPv6 / DualStack prerequisite)
        self.cmd(
            'network vnet update -g {rg} -n {vnet} '
            '--private-endpoint-vnet-policies Basic'
        )

        self.cmd(
            'network vnet subnet update -g {rg} -n {subnet_pls} --vnet-name {vnet} '
            '--disable-private-link-service-network-policies'
        )

        # Private Endpoint subnet (dual-stack)
        self.cmd(
            'network vnet subnet create -g {rg} -n {subnet_pe} --vnet-name {vnet} '
            '--address-prefixes {subnet_pe_ipv4} {subnet_pe_ipv6} '
            '--default-outbound false'
        )

        self.cmd(
            'network vnet subnet update -g {rg} -n {subnet_pe} --vnet-name {vnet} '
            '--private-endpoint-network-policies RouteTableEnabled'
        )

        # ---- Storage PLR ----
        pr = self.cmd(
            'storage account private-link-resource list --account-name {sa} -g {rg}'
        ).get_output_in_json()
        self.kwargs['group_id'] = pr[0]['groupId']

        storage = self.cmd(
            'storage account show -n {sa} -g {rg}'
        ).get_output_in_json()
        self.kwargs['sa_id'] = storage['id']

        # IPv4
        self.cmd(
            'network private-endpoint create -g {rg} -n {pe_v4} '
            '--vnet-name {vnet} --subnet {subnet_pe} '
            '--group-id {group_id} '
            '--private-connection-resource-id {sa_id} '
            '--connection-name {pe_conn} '
            '-l {location} --nic-name {nic_v4} '
            '--ip-version-type IPv4',
            checks=[
                self.check('ipVersionType', 'IPv4'),
            ]
        )

        # IPv6
        self.cmd(
            'network private-endpoint create -g {rg} -n {pe_v6} '
            '--vnet-name {vnet} --subnet {subnet_pe} '
            '--group-id {group_id} '
            '--private-connection-resource-id {sa_id} '
            '--connection-name {pe_conn} '
            '-l {location} --nic-name {nic_v6} '
            '--ip-version-type IPv6',
            checks=[
                self.check('ipVersionType', 'IPv6'),
            ]
        )

        # DualStack
        self.cmd(
            'network private-endpoint create -g {rg} -n {pe_ds} '
            '--vnet-name {vnet} --subnet {subnet_pe} '
            '--group-id {group_id} '
            '--private-connection-resource-id {sa_id} '
            '--connection-name {pe_conn} '
            '-l {location} --nic-name {nic_ds} '
            '--ip-version-type DualStack',
            checks=[
                self.check('ipVersionType', 'DualStack'),
            ]
        )

        # Update PE: IPv4 -> DualStack
        self.cmd(
            'network private-endpoint update -g {rg} -n {pe_v4} '
            '--ip-version-type DualStack',
            checks=[
                self.check('name', '{pe_v4}'),
                self.check('ipVersionType', 'DualStack'),
                self.check('provisioningState', 'Succeeded'),
            ]
        )

        # Update PE: DualStack -> IPv6 (not allowed, expect failure)
        self.cmd(
            'network private-endpoint update -g {rg} -n {pe_v4} '
            '--ip-version-type IPv6',
            expect_failure=True
        )

        # Basic list checks
        self.cmd('network private-endpoint list -g {rg}', checks=[
            self.check('length(@)', 3)
        ])


class NetworkApplicationGatewayHttpSettingsScenario(ScenarioTest):
    @ResourceGroupPreparer(name_prefix='test_ag', location='eastus')
    def test_network_application_gateway_http_settings_validate_flags(self, resource_group):
        self.kwargs.update({
            'vnet': 'vnet1',
            'subnet': 'subnet1',
            'vnet_prefix': '10.0.0.0/16',
            'subnet_prefix': '10.0.0.0/24',
            'pip': 'pip1',
            'ag': 'ag1',
            'httpsettingname': 'mysettings1',
            'addresspool': 'myaddresspool1',
            'listener': 'mylistener1',
            'rule': 'myrule1',
        })

        # Create vnet, pip, application-gateway
        self.cmd('network vnet create -g {rg} -n {vnet} --address-prefix {vnet_prefix} --subnet-name {subnet} --subnet-prefix {subnet_prefix}')
        self.cmd('network public-ip create -g {rg} -n {pip} --sku Standard --allocation-method Static')
        self.cmd('network application-gateway create -g {rg} -n {ag} --vnet-name {vnet} --subnet {subnet} --public-ip-address {pip} --priority 1001 --sku Standard_v2')

        # Create http settings
        self.cmd('network application-gateway http-settings create -g {rg} --gateway-name {ag} -n {httpsettingname} '
                 '--port 443 --protocol Https --cookie-based-affinity disabled '
                 '--validate-cert-chain-and-expiry false --validate-sni true', checks=[
            self.check('name', '{httpsettingname}'),
            self.check('port', 443),
            self.check('protocol', 'Https'),
            self.check('cookieBasedAffinity', 'Disabled'),
            self.check('validateCertChainAndExpiry', False),
            self.check('validateSNI', True),
        ])

        # validate flags under backendHttpSettingsCollection for the created http setting
        self.cmd('network application-gateway show -g {rg} -n {ag}', checks=[
            self.check("backendHttpSettingsCollection[?name=='mysettings1'] | [0].validateCertChainAndExpiry", False),
            self.check("backendHttpSettingsCollection[?name=='mysettings1'] | [0].validateSNI", True),
        ])

        # Create address-pool and http-listener
        self.cmd('network application-gateway address-pool create -g {rg} --gateway-name {ag} -n {addresspool}')
        self.cmd('network application-gateway http-listener create -g {rg} --gateway-name {ag} -n {listener} --no-wait '
                 '--frontend-port appGatewayFrontendPort --host-name www.test.com')

        # Create rule, then show app-gateway again and check validate flags are still the same
        self.cmd('network application-gateway rule create -g {rg} --gateway-name {ag} -n {rule} --rule-type Basic '
                 '--http-listener {listener} --address-pool {addresspool} --http-settings {httpsettingname} --priority 1004')

        self.cmd('network application-gateway show -g {rg} -n {ag}', checks=[
            self.check("backendHttpSettingsCollection[?name=='mysettings1'] | [0].validateCertChainAndExpiry", False),
            self.check("backendHttpSettingsCollection[?name=='mysettings1'] | [0].validateSNI", True),
        ])


class ApplicationGatewayValidateFlagsScenarioTest(ScenarioTest):
    @ResourceGroupPreparer(name_prefix='cli_test_ag_validate_flags', location='eastus')
    def test_ag_rule_create_preserves_http_settings_validate_flags(self, resource_group, resource_group_location):
        self.kwargs.update({
            'rg': resource_group,
            'loc': resource_group_location,
            'vnet': self.create_random_name('vnet', 15),
            'subnet': 'subnet1',
            'pip': self.create_random_name('pip', 15),
            'ag': self.create_random_name('ag', 15),
            'settings': 'mysettings1',
            'pool': 'myaddresspool1',
            'listener': 'mylistener',
            'rule': 'repro-rule'
        })

        self.cmd(
            'az network vnet create -g {rg} -n {vnet} '
            '--address-prefix 10.0.0.0/16 '
            '--subnet-name {subnet} --subnet-prefix 10.0.0.0/24'
        )
        self.cmd('az network public-ip create -g {rg} -n {pip} --sku Standard --allocation-method Static')

        self.cmd(
            'az network application-gateway create -g {rg} -n {ag} '
            '--vnet-name {vnet} --subnet {subnet} '
            '--public-ip-address {pip} '
            '--priority 1001 --sku Standard_v2'
        )

        self.cmd(
            'az network application-gateway http-settings create -g {rg} --gateway-name {ag} '
            '-n {settings} --port 443 --protocol Https '
            '--cookie-based-affinity disabled '
            '--validate-cert-chain-and-expiry false --validate-sni false',
            checks=[
                self.check('validateCertChainAndExpiry', False),
                self.check('validateSNI', False)
            ]
        )

        self.cmd('az network application-gateway address-pool create -g {rg} --gateway-name {ag} -n {pool}')
        self.cmd(
            'az network application-gateway http-listener create -g {rg} --gateway-name {ag} -n {listener} '
            '--frontend-port appGatewayFrontendPort --host-name www.test.com'
        )

        self.cmd(
            'az network application-gateway rule create -g {rg} --gateway-name {ag} -n {rule} '
            '--rule-type Basic --http-listener {listener} '
            '--address-pool {pool} --http-settings {settings} '
            '--priority 1004'
        )

        self.cmd(
            'az network application-gateway show -g {rg} -n {ag} '
            '--query "backendHttpSettingsCollection[?name==\'{settings}\'] | [0]"',
            checks=[
                self.check('validateCertChainAndExpiry', False),
                self.check('validateSNI', False)
            ]
        )


if __name__ == '__main__':
    unittest.main()