/// <summary>
 /// Creates or updates a network watcher in the specified resource group.
 /// </summary>
 /// <param name='operations'>
 /// The operations group for this extension method.
 /// </param>
 /// <param name='resourceGroupName'>
 /// The name of the resource group.
 /// </param>
 /// <param name='networkWatcherName'>
 /// The name of the network watcher.
 /// </param>
 /// <param name='parameters'>
 /// Parameters that define the network watcher resource.
 /// </param>
 public static NetworkWatcher CreateOrUpdate(this INetworkWatchersOperations operations, string resourceGroupName, string networkWatcherName, NetworkWatcher parameters)
 {
     return(operations.CreateOrUpdateAsync(resourceGroupName, networkWatcherName, parameters).GetAwaiter().GetResult());
 }
 /// <summary>
 /// Creates or updates a network watcher in the specified resource group.
 /// </summary>
 /// <param name='operations'>
 /// The operations group for this extension method.
 /// </param>
 /// <param name='resourceGroupName'>
 /// The name of the resource group.
 /// </param>
 /// <param name='networkWatcherName'>
 /// The name of the network watcher.
 /// </param>
 /// <param name='parameters'>
 /// Parameters that define the network watcher resource.
 /// </param>
 /// <param name='cancellationToken'>
 /// The cancellation token.
 /// </param>
 public static async Task <NetworkWatcher> CreateOrUpdateAsync(this INetworkWatchersOperations operations, string resourceGroupName, string networkWatcherName, NetworkWatcher parameters, CancellationToken cancellationToken = default(CancellationToken))
 {
     using (var _result = await operations.CreateOrUpdateWithHttpMessagesAsync(resourceGroupName, networkWatcherName, parameters, null, cancellationToken).ConfigureAwait(false))
     {
         return(_result.Body);
     }
 }
        public void TopologyApiTest()
        {
            var handler1 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };
            var handler2 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };
            var handler3 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };

            using (MockContext context = MockContext.Start(this.GetType()))
            {
                var resourcesClient         = ResourcesManagementTestUtilities.GetResourceManagementClientWithHandler(context, handler1);
                var networkManagementClient = NetworkManagementTestUtilities.GetNetworkManagementClientWithHandler(context, handler2);
                var computeManagementClient = NetworkManagementTestUtilities.GetComputeManagementClientWithHandler(context, handler3);

                string location = "eastus";

                string resourceGroupName1 = TestUtilities.GenerateName();
                resourcesClient.ResourceGroups.CreateOrUpdate(resourceGroupName1,
                                                              new ResourceGroup
                {
                    Location = location
                });

                string virtualMachineName       = TestUtilities.GenerateName();
                string networkSecurityGroupName = virtualMachineName + "-nsg";
                string networkInterfaceName     = TestUtilities.GenerateName();

                //Deploy Vm from template
                Deployments.CreateVm(
                    resourcesClient: resourcesClient,
                    resourceGroupName: resourceGroupName1,
                    location: location,
                    virtualMachineName: virtualMachineName,
                    storageAccountName: TestUtilities.GenerateName(),
                    networkInterfaceName: networkInterfaceName,
                    networkSecurityGroupName: networkSecurityGroupName,
                    diagnosticsStorageAccountName: TestUtilities.GenerateName(),
                    deploymentName: TestUtilities.GenerateName()
                    );

                string resourceGroupName2 = TestUtilities.GenerateName();
                resourcesClient.ResourceGroups.CreateOrUpdate(resourceGroupName2,
                                                              new ResourceGroup
                {
                    Location = location
                });

                string         networkWatcherName = TestUtilities.GenerateName();
                NetworkWatcher properties         = new NetworkWatcher();
                properties.Location = location;

                //Create NetworkWatcher
                var createNetworkWatcher = networkManagementClient.NetworkWatchers.CreateOrUpdate(resourceGroupName2, networkWatcherName, properties);

                TopologyParameters tpProperties = new TopologyParameters()
                {
                    TargetResourceGroupName = resourceGroupName1
                };

                var getVm = computeManagementClient.VirtualMachines.Get(resourceGroupName1, virtualMachineName);

                //Get the current network topology of the resourceGroupName1
                var getTopology = networkManagementClient.NetworkWatchers.GetTopology(resourceGroupName2, networkWatcherName, tpProperties);


                //Getting infromation about VM from topology
                TopologyResource vmResource = getTopology.Resources[2];

                //Verify that topology contain right number of resources (9 resources from template)
                Assert.Equal(9, getTopology.Resources.Count);

                //Verify that topology contain information about acreated VM
                Assert.Equal(virtualMachineName, vmResource.Name);
                Assert.Equal(getVm.Id, vmResource.Id);
                Assert.Equal(networkInterfaceName, vmResource.Associations.FirstOrDefault().Name);
                Assert.Equal(getVm.NetworkProfile.NetworkInterfaces.FirstOrDefault().Id, vmResource.Associations.FirstOrDefault().ResourceId);
                Assert.Equal("Contains", vmResource.Associations.FirstOrDefault().AssociationType);
            }
        }
示例#4
0
 public void Init()
 {
     Target = new NetworkWatcher();
 }
        public void CheckConnectivityVmToInternetTest()
        {
            var handler1 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };
            var handler2 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };
            var handler3 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };

            using (MockContext context = MockContext.Start(this.GetType().FullName))
            {
                var resourcesClient         = ResourcesManagementTestUtilities.GetResourceManagementClientWithHandler(context, handler1, true);
                var networkManagementClient = NetworkManagementTestUtilities.GetNetworkManagementClientWithHandler(context, handler2);
                var computeManagementClient = NetworkManagementTestUtilities.GetComputeManagementClientWithHandler(context, handler3);

                string location = "westcentralus";

                string resourceGroupName = TestUtilities.GenerateName();
                resourcesClient.ResourceGroups.CreateOrUpdate(resourceGroupName,
                                                              new ResourceGroup
                {
                    Location = location
                });

                string virtualMachineName       = TestUtilities.GenerateName();
                string networkInterfaceName     = TestUtilities.GenerateName();
                string networkSecurityGroupName = virtualMachineName + "-nsg";

                //Deploy VM with a template
                DeploymentUpdate.CreateVm(
                    resourcesClient: resourcesClient,
                    resourceGroupName: resourceGroupName,
                    location: location,
                    virtualMachineName: virtualMachineName,
                    storageAccountName: TestUtilities.GenerateName(),
                    networkInterfaceName: networkInterfaceName,
                    networkSecurityGroupName: networkSecurityGroupName,
                    diagnosticsStorageAccountName: TestUtilities.GenerateName(),
                    deploymentName: TestUtilities.GenerateName()
                    );

                var getVm = computeManagementClient.VirtualMachines.Get(resourceGroupName, virtualMachineName);

                //Deploy networkWatcherAgent on VM
                VirtualMachineExtension parameters = new VirtualMachineExtension();
                parameters.Publisher                   = "Microsoft.Azure.NetworkWatcher.Edp";
                parameters.TypeHandlerVersion          = "1.4";
                parameters.VirtualMachineExtensionType = "NetworkWatcherAgentWindows";
                parameters.Location = location;

                var addExtension = computeManagementClient.VirtualMachineExtensions.CreateOrUpdate(resourceGroupName, getVm.Name, "NetworkWatcherAgent", parameters);

                string         networkWatcherName = TestUtilities.GenerateName();
                NetworkWatcher properties         = new NetworkWatcher();
                properties.Location = location;

                //Create network Watcher
                var createNetworkWatcher = networkManagementClient.NetworkWatchers.CreateOrUpdate(resourceGroupName, networkWatcherName, properties);

                ConnectivityParameters connectivityParameters = new ConnectivityParameters();
                connectivityParameters.Source              = new ConnectivitySource();
                connectivityParameters.Source.ResourceId   = getVm.Id;
                connectivityParameters.Destination         = new ConnectivityDestination();
                connectivityParameters.Destination.Address = "bing.com";
                connectivityParameters.Destination.Port    = 80;

                var connectivityCheck = networkManagementClient.NetworkWatchers.CheckConnectivity(resourceGroupName, networkWatcherName, connectivityParameters);

                //Validation
                Assert.Equal("Reachable", connectivityCheck.ConnectionStatus);
                Assert.Equal(0, connectivityCheck.ProbesFailed);
                Assert.Equal("Source", connectivityCheck.Hops.FirstOrDefault().Type);
                Assert.Equal("Internet", connectivityCheck.Hops.LastOrDefault().Type);
            }
        }
        public void VerifyIpFlowApiTest()
        {
            var handler1 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };
            var handler2 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };
            var handler3 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };

            using (MockContext context = MockContext.Start(this.GetType()))
            {
                var resourcesClient         = ResourcesManagementTestUtilities.GetResourceManagementClientWithHandler(context, handler1);
                var networkManagementClient = NetworkManagementTestUtilities.GetNetworkManagementClientWithHandler(context, handler2);
                var computeManagementClient = NetworkManagementTestUtilities.GetComputeManagementClientWithHandler(context, handler3);

                string location = "eastus";

                string resourceGroupName = TestUtilities.GenerateName();
                resourcesClient.ResourceGroups.CreateOrUpdate(resourceGroupName,
                                                              new ResourceGroup
                {
                    Location = location
                });

                string virtualMachineName1      = TestUtilities.GenerateName();
                string networkInterfaceName1    = TestUtilities.GenerateName();
                string networkSecurityGroupName = virtualMachineName1 + "-nsg";

                //Deploy VM with a template
                Deployments.CreateVm(
                    resourcesClient: resourcesClient,
                    resourceGroupName: resourceGroupName,
                    location: location,
                    virtualMachineName: virtualMachineName1,
                    storageAccountName: TestUtilities.GenerateName(),
                    networkInterfaceName: networkInterfaceName1,
                    networkSecurityGroupName: networkSecurityGroupName,
                    diagnosticsStorageAccountName: TestUtilities.GenerateName(),
                    deploymentName: TestUtilities.GenerateName()
                    );

                string         networkWatcherName = TestUtilities.GenerateName();
                NetworkWatcher properties         = new NetworkWatcher();
                properties.Location = location;

                //Create network Watcher
                var createNetworkWatcher = networkManagementClient.NetworkWatchers.CreateOrUpdate(resourceGroupName, networkWatcherName, properties);

                var    getVm1         = computeManagementClient.VirtualMachines.Get(resourceGroupName, virtualMachineName1);
                string localIPAddress = networkManagementClient.NetworkInterfaces.Get(resourceGroupName, networkInterfaceName1).IpConfigurations.FirstOrDefault().PrivateIPAddress;


                string securityRule1 = TestUtilities.GenerateName();

                // Add a security rule
                var SecurityRule = new SecurityRule()
                {
                    Name        = securityRule1,
                    Access      = SecurityRuleAccess.Deny,
                    Description = "Test outbound security rule",
                    DestinationAddressPrefix = "*",
                    DestinationPortRange     = "80",
                    Direction           = SecurityRuleDirection.Outbound,
                    Priority            = 501,
                    Protocol            = SecurityRuleProtocol.Tcp,
                    SourceAddressPrefix = "*",
                    SourcePortRange     = "*",
                };

                var nsg = networkManagementClient.NetworkSecurityGroups.Get(resourceGroupName, networkSecurityGroupName);
                nsg.SecurityRules.Add(SecurityRule);
                networkManagementClient.NetworkSecurityGroups.CreateOrUpdate(resourceGroupName, networkSecurityGroupName, nsg);

                VerificationIPFlowParameters ipFlowProperties = new VerificationIPFlowParameters()
                {
                    TargetResourceId = getVm1.Id,
                    Direction        = "Outbound",
                    Protocol         = "TCP",
                    LocalPort        = "80",
                    RemotePort       = "80",
                    LocalIPAddress   = localIPAddress,
                    RemoteIPAddress  = "12.11.12.14"
                };

                //Verify IP flow from a VM to a location given the configured  rule
                var verifyIpFlow = networkManagementClient.NetworkWatchers.VerifyIPFlow(resourceGroupName, networkWatcherName, ipFlowProperties);

                //Verify validity of the result
                Assert.Equal("Deny", verifyIpFlow.Access);
                Assert.Equal("securityRules/" + securityRule1, verifyIpFlow.RuleName);
            }
        }
        public void FlowLogApiTest()
        {
            var handler1 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };
            var handler2 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };
            var handler3 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };
            var handler4 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };
            var handler5 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };

            using (MockContext context = MockContext.Start(this.GetType()))
            {
                var resourcesClient                     = ResourcesManagementTestUtilities.GetResourceManagementClientWithHandler(context, handler1);
                var networkManagementClient             = NetworkManagementTestUtilities.GetNetworkManagementClientWithHandler(context, handler2);
                var computeManagementClient             = NetworkManagementTestUtilities.GetComputeManagementClientWithHandler(context, handler3);
                var storageManagementClient             = NetworkManagementTestUtilities.GetStorageManagementClientWithHandler(context, handler4);
                var operationalInsightsManagementClient = NetworkManagementTestUtilities.GetOperationalInsightsManagementClientWithHandler(context, handler5);

                string location          = "eastus2euap";
                string workspaceLocation = "East US";

                string resourceGroupName = TestUtilities.GenerateName();
                resourcesClient.ResourceGroups.CreateOrUpdate(resourceGroupName,
                                                              new ResourceGroup
                {
                    Location = location
                });

                //Create network security group
                string networkSecurityGroupName = TestUtilities.GenerateName();

                var networkSecurityGroup = new NetworkSecurityGroup()
                {
                    Location = location,
                };

                // Put Nsg
                var putNsgResponse = networkManagementClient.NetworkSecurityGroups.CreateOrUpdate(resourceGroupName, networkSecurityGroupName, networkSecurityGroup);

                // Get NSG
                var getNsgResponse = networkManagementClient.NetworkSecurityGroups.Get(resourceGroupName, networkSecurityGroupName);

                string         networkWatcherName = TestUtilities.GenerateName();
                NetworkWatcher properties         = new NetworkWatcher();
                properties.Location = location;

                //Create network Watcher
                var createNetworkWatcher = networkManagementClient.NetworkWatchers.CreateOrUpdate(resourceGroupName, networkWatcherName, properties);

                //Create storage
                string storageName = TestUtilities.GenerateName();

                var storageParameters = new StorageAccountCreateParameters()
                {
                    Location = location,
                    Kind     = Kind.Storage,
                    Sku      = new Sku
                    {
                        Name = SkuName.StandardLRS
                    }
                };

                var storageAccount = storageManagementClient.StorageAccounts.Create(resourceGroupName, storageName, storageParameters);

                //create workspace
                string workspaceName = TestUtilities.GenerateName();

                var workSpaceParameters = new Workspace()
                {
                    Location = workspaceLocation
                };

                var workspace = operationalInsightsManagementClient.Workspaces.CreateOrUpdate(resourceGroupName, workspaceName, workSpaceParameters);

                FlowLogInformation configParameters = new FlowLogInformation()
                {
                    TargetResourceId = getNsgResponse.Id,
                    Enabled          = true,
                    StorageId        = storageAccount.Id,
                    RetentionPolicy  = new RetentionPolicyParameters
                    {
                        Days    = 5,
                        Enabled = true
                    },
                    FlowAnalyticsConfiguration = new TrafficAnalyticsProperties()
                    {
                        NetworkWatcherFlowAnalyticsConfiguration = new TrafficAnalyticsConfigurationProperties()
                        {
                            Enabled             = true,
                            WorkspaceId         = workspace.CustomerId,
                            WorkspaceRegion     = workspace.Location,
                            WorkspaceResourceId = workspace.Id
                        }
                    }
                };


                //configure flowlog and TA
                var configureFlowLog1 = networkManagementClient.NetworkWatchers.SetFlowLogConfiguration(resourceGroupName, networkWatcherName, configParameters);

                FlowLogStatusParameters flowLogParameters = new FlowLogStatusParameters()
                {
                    TargetResourceId = getNsgResponse.Id
                };

                var queryFlowLogStatus1 = networkManagementClient.NetworkWatchers.GetFlowLogStatus(resourceGroupName, networkWatcherName, flowLogParameters);

                //check both flowlog and TA config and enabled status
                Assert.Equal(queryFlowLogStatus1.TargetResourceId, configParameters.TargetResourceId);
                Assert.True(queryFlowLogStatus1.Enabled);
                Assert.Equal(queryFlowLogStatus1.StorageId, configParameters.StorageId);
                Assert.Equal(queryFlowLogStatus1.RetentionPolicy.Days, configParameters.RetentionPolicy.Days);
                Assert.Equal(queryFlowLogStatus1.RetentionPolicy.Enabled, configParameters.RetentionPolicy.Enabled);
                Assert.True(queryFlowLogStatus1.FlowAnalyticsConfiguration.NetworkWatcherFlowAnalyticsConfiguration.Enabled);
                Assert.Equal(queryFlowLogStatus1.FlowAnalyticsConfiguration.NetworkWatcherFlowAnalyticsConfiguration.WorkspaceId,
                             configParameters.FlowAnalyticsConfiguration.NetworkWatcherFlowAnalyticsConfiguration.WorkspaceId);
                Assert.Equal(queryFlowLogStatus1.FlowAnalyticsConfiguration.NetworkWatcherFlowAnalyticsConfiguration.WorkspaceRegion,
                             configParameters.FlowAnalyticsConfiguration.NetworkWatcherFlowAnalyticsConfiguration.WorkspaceRegion);
                Assert.Equal(queryFlowLogStatus1.FlowAnalyticsConfiguration.NetworkWatcherFlowAnalyticsConfiguration.WorkspaceResourceId,
                             configParameters.FlowAnalyticsConfiguration.NetworkWatcherFlowAnalyticsConfiguration.WorkspaceResourceId);

                //disable TA
                configParameters.FlowAnalyticsConfiguration.NetworkWatcherFlowAnalyticsConfiguration.Enabled = false;
                var configureFlowLog2   = networkManagementClient.NetworkWatchers.SetFlowLogConfiguration(resourceGroupName, networkWatcherName, configParameters);
                var queryFlowLogStatus2 = networkManagementClient.NetworkWatchers.GetFlowLogStatus(resourceGroupName, networkWatcherName, flowLogParameters);

                //check TA disabled and ensure flowlog config is unchanged
                Assert.Equal(queryFlowLogStatus2.TargetResourceId, configParameters.TargetResourceId);
                Assert.True(queryFlowLogStatus2.Enabled);
                Assert.Equal(queryFlowLogStatus2.StorageId, configParameters.StorageId);
                Assert.Equal(queryFlowLogStatus2.RetentionPolicy.Days, configParameters.RetentionPolicy.Days);
                Assert.Equal(queryFlowLogStatus2.RetentionPolicy.Enabled, configParameters.RetentionPolicy.Enabled);
                Assert.False(queryFlowLogStatus2.FlowAnalyticsConfiguration.NetworkWatcherFlowAnalyticsConfiguration.Enabled);

                //disable flowlog (and TA)
                configParameters.Enabled = false;
                var configureFlowLog3   = networkManagementClient.NetworkWatchers.SetFlowLogConfiguration(resourceGroupName, networkWatcherName, configParameters);
                var queryFlowLogStatus3 = networkManagementClient.NetworkWatchers.GetFlowLogStatus(resourceGroupName, networkWatcherName, flowLogParameters);

                //check both flowlog and TA disabled
                Assert.False(queryFlowLogStatus3.Enabled);
                Assert.False(queryFlowLogStatus3.FlowAnalyticsConfiguration.NetworkWatcherFlowAnalyticsConfiguration.Enabled);
            }
        }
示例#8
0
        public void DeleteConnectionMonitorTest()
        {
            var handler1 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };
            var handler2 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };
            var handler3 = new RecordedDelegatingHandler {
                StatusCodeToReturn = HttpStatusCode.OK
            };

            using (MockContext context = MockContext.Start(this.GetType()))
            {
                var resourcesClient         = ResourcesManagementTestUtilities.GetResourceManagementClientWithHandler(context, handler1, true);
                var networkManagementClient = NetworkManagementTestUtilities.GetNetworkManagementClientWithHandler(context, handler2);
                var computeManagementClient = NetworkManagementTestUtilities.GetComputeManagementClientWithHandler(context, handler3);

                string location = "centraluseuap";

                string resourceGroupName = TestUtilities.GenerateName();
                resourcesClient.ResourceGroups.CreateOrUpdate(resourceGroupName,
                                                              new ResourceGroup
                {
                    Location = location
                });

                string virtualMachineName       = TestUtilities.GenerateName();
                string networkInterfaceName     = TestUtilities.GenerateName();
                string networkSecurityGroupName = virtualMachineName + "-nsg";

                //Deploy VM with a template
                DeploymentUpdate.CreateVm(
                    resourcesClient: resourcesClient,
                    resourceGroupName: resourceGroupName,
                    location: location,
                    virtualMachineName: virtualMachineName,
                    storageAccountName: TestUtilities.GenerateName(),
                    networkInterfaceName: networkInterfaceName,
                    networkSecurityGroupName: networkSecurityGroupName,
                    diagnosticsStorageAccountName: TestUtilities.GenerateName(),
                    deploymentName: TestUtilities.GenerateName()
                    );

                var getVm = computeManagementClient.VirtualMachines.Get(resourceGroupName, virtualMachineName);

                //Deploy networkWatcherAgent on VM
                VirtualMachineExtension parameters = new VirtualMachineExtension
                {
                    Publisher                   = "Microsoft.Azure.NetworkWatcher",
                    TypeHandlerVersion          = "1.4",
                    VirtualMachineExtensionType = "NetworkWatcherAgentWindows",
                    Location = location
                };

                var addExtension = computeManagementClient.VirtualMachineExtensions.CreateOrUpdate(resourceGroupName, getVm.Name, "NetworkWatcherAgent", parameters);

                string         networkWatcherName = TestUtilities.GenerateName();
                NetworkWatcher properties         = new NetworkWatcher
                {
                    Location = location
                };

                //Create network Watcher
                var createNetworkWatcher = networkManagementClient.NetworkWatchers.CreateOrUpdate(resourceGroupName, networkWatcherName, properties);

                string            connectionMonitorName1 = TestUtilities.GenerateName();
                string            connectionMonitorName2 = TestUtilities.GenerateName();
                ConnectionMonitor cm = new ConnectionMonitor
                {
                    Location = location,
                    Source   = new ConnectionMonitorSource
                    {
                        ResourceId = getVm.Id
                    },
                    Destination = new ConnectionMonitorDestination
                    {
                        Address = "bing.com",
                        Port    = 80
                    },
                    MonitoringIntervalInSeconds = 30,
                    AutoStart = false
                };

                var connectionMonitor1 = networkManagementClient.ConnectionMonitors.CreateOrUpdate(resourceGroupName, networkWatcherName, connectionMonitorName1, cm);
                var connectionMonitor2 = networkManagementClient.ConnectionMonitors.CreateOrUpdate(resourceGroupName, networkWatcherName, connectionMonitorName2, cm);

                var getConnectionMonitors1 = networkManagementClient.ConnectionMonitors.List(resourceGroupName, networkWatcherName);
                Assert.Equal(2, getConnectionMonitors1.Count());

                networkManagementClient.ConnectionMonitors.Delete(resourceGroupName, networkWatcherName, connectionMonitorName2);
                var getConnectionMonitors2 = networkManagementClient.ConnectionMonitors.List(resourceGroupName, networkWatcherName);
                Assert.Single(getConnectionMonitors2);
            }
        }