Example #1
0
        public static void Run([QueueTrigger("upgraderequests", Connection = "AzureWebJobsStorage")] UpdateLoadBalancerEntity myQueueItem, ILogger log)
        {
            log.LogInformation($"C# Queue trigger function processed: {myQueueItem.RowKey}");
            //TO DO
            //STORE THE CONFIG IN THE JSON FORMAT (EITHER BLOB OR COSMOS)
            string  runbookUri = Environment.GetEnvironmentVariable("WebHookUri", EnvironmentVariableTarget.Process);
            dynamic response   = ResilientRestClient.PostAsync <dynamic>(runbookUri, null, myQueueItem).Result;

            log.LogInformation($"Job Id = {response.JobIds}");
        }
Example #2
0
        public static async Task Run([TimerTrigger("0 */1 * * * *")] TimerInfo myTimer, ILogger log, [Table("dselbtable")] CloudTable loadbalancerconfigTable)
        {
            log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");

            TableQuerySegment <UpdateLoadBalancerEntity> segment = null;
            TableBatchOperation batchOperation = new TableBatchOperation();

            log.LogInformation($"Deleting all resources for {loadbalancerconfigTable.Name}");
            while (segment == null || segment.ContinuationToken != null)
            {
                segment = await loadbalancerconfigTable.ExecuteQuerySegmentedAsync(new TableQuery <UpdateLoadBalancerEntity>().Take(500), segment?.ContinuationToken);

                Parallel.ForEach(segment.Results, async entity =>
                {
                    await loadbalancerconfigTable.ExecuteAsync(TableOperation.Delete(entity));
                });
            }
            if (batchOperation.Count > 0)
            {
                await loadbalancerconfigTable.ExecuteBatchAsync(batchOperation);
            }

            //Get Token
            string token = AuthHelper.GetTokenAsync().Result;

            log.LogInformation($"Token Received: {token}");

            string        subscriptionsUri = "https://management.azure.com/subscriptions?api-version=2016-06-01";
            Subscriptions subscriptions    = await ResilientRestClient.GetAsync <Subscriptions>(subscriptionsUri, token);

            log.LogInformation($"Subs Received");

            //Query SubscriptionIDs which has Gateway Connections
            string query = "where type =~ 'microsoft.network/connections'| distinct subscriptionId ";
            Dictionary <string, int> options = new Dictionary <string, int>();

            options["$skip"] = 0;
            Dictionary <string, object> requestBodyObj = new Dictionary <string, object>();
            List <string> subscriptionIds = subscriptions.value.Select(subs => subs.subscriptionId).ToList();

            requestBodyObj.Add("subscriptions", subscriptionIds);
            requestBodyObj.Add("query", query);
            requestBodyObj.Add("options", options);
            string        resourceGraphUri = "https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2018-09-01-preview";
            List <string> expressRouteConnectedSubscriptions = new List <string>();
            //TEST CASE
            string subId = Environment.GetEnvironmentVariable("TestSubscriptionID", EnvironmentVariableTarget.Process);

            expressRouteConnectedSubscriptions.Add(subId);
            //Commenting for test
            // ResourceGraphResponse resourcesubs = ResilientRestClient.PostAsync<ResourceGraphResponse>(resourceGraphUri, token, requestBodyObj).Result;
            // foreach (List<string> row in resourcesubs.data.rows)
            // {
            //     expressRouteConnectedSubscriptions.Add(row[0]);
            // }
            // log.LogInformation($"The number of subs are {expressRouteConnectedSubscriptions.Count}");

            //TODO ADD Logic to clear the table or after automation job completion trigger an update to remove the upgraded LB from table

            //Query for Load Balancers
            string lbquery = "where type =~ 'Microsoft.Network/loadbalancers'| where tostring(sku.name) =='Basic' | project id, subscriptionId, resourceGroup, name, location";
            Dictionary <string, int> lboptions = new Dictionary <string, int>();

            options["$skip"] = 0;
            Dictionary <string, object> lbrequestBodyObj = new Dictionary <string, object>();

            lbrequestBodyObj.Add("subscriptions", expressRouteConnectedSubscriptions);
            lbrequestBodyObj.Add("query", lbquery);
            lbrequestBodyObj.Add("options", lboptions);

            List <LoadBalancerObj> loadBalancers = new List <LoadBalancerObj>();

            ResourceGraphResponse lbs = ResilientRestClient.PostAsync <ResourceGraphResponse>(resourceGraphUri, token, lbrequestBodyObj).Result;
            int i = 1;

            foreach (List <string> row in lbs.data.rows)
            {
                LoadBalancerObj lb = new LoadBalancerObj
                {
                    ResourceId     = row[0],
                    SubscriptionId = row[1],
                    ResourceGroup  = row[2],
                    Name           = row[3],
                    Location       = row[4]
                };
                loadBalancers.Add(lb);
            }
            while (lbs.skipToken != null)
            {
                log.LogInformation(i.ToString());
                Dictionary <string, int> nextSkip = new Dictionary <string, int>();
                nextSkip["$skip"] = i * 1000;
                Dictionary <string, object> updatedrequestBodyObj = new Dictionary <string, object>();
                updatedrequestBodyObj["subscriptions"] = expressRouteConnectedSubscriptions;
                updatedrequestBodyObj["query"]         = lbquery;
                updatedrequestBodyObj["$skipToken"]    = lbs.skipToken;
                updatedrequestBodyObj["options"]       = nextSkip;
                lbs = ResilientRestClient.PostAsync <ResourceGraphResponse>(resourceGraphUri, token, updatedrequestBodyObj).Result;
                foreach (List <string> row in lbs.data.rows)
                {
                    LoadBalancerObj lb = new LoadBalancerObj
                    {
                        ResourceId     = row[0],
                        SubscriptionId = row[1],
                        ResourceGroup  = row[2],
                        Name           = row[3],
                        Location       = row[4]
                    };
                    loadBalancers.Add(lb);
                }
                i++;
            }

            Parallel.ForEach(loadBalancers, async lb =>
            {
                UpdateLoadBalancerEntity loadBalancerEntity = new UpdateLoadBalancerEntity
                {
                    PartitionKey  = lb.SubscriptionId,
                    RowKey        = lb.Name,
                    Location      = lb.Location,
                    ResourceGroup = lb.ResourceGroup,
                    ResourceId    = lb.ResourceId
                };
                TableOperation insertOperation = TableOperation.InsertOrMerge(loadBalancerEntity);
                await loadbalancerconfigTable.ExecuteAsync(insertOperation);
            });
        }
Example #3
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log
            //,[Queue("retryresources", Connection = "AzureWebJobsStorage")] ICollector<ResourceHealthDto> retryQueue
            )
        {
            var requestBody = await new StreamReader(req.Body).ReadToEndAsync();

            log.LogInformation("requestBodyis");
            log.LogInformation(requestBody);

            //Process ResourceHealth Alert
            if (requestBody.Contains("Resource Health"))
            {
                var resourceHealthAlert = JsonConvert.DeserializeObject <ResourceHealthAlert>(requestBody);
                log.LogInformation(resourceHealthAlert.schemaId);
                var alertObj        = CosmosHelper.GetResourceHealthDtoMapping(resourceHealthAlert);
                var alertHistoryObj = CosmosHelper.GetDtoHistoryMapping(resourceHealthAlert);

                log.LogInformation("Resource Health Alert Id: " + alertObj.alertId);
                log.LogInformation("Resource Subscription: " + alertObj.subscriptionId);
                log.LogInformation("Resource Id: " + alertObj.resourceId);
                log.LogInformation("Resource Status: " + alertObj.currentHealthStatus);

                try
                {
                    List <string> subs = new List <string>
                    {
                        alertObj.subscriptionId
                    };
                    string token = AuthHelper.GetTokenAsync().Result;
                    log.LogInformation($"Token Received: {token}");

                    /*  Below is to do the quick testing for resolution of access token
                     * string linkId = "subscriptions/a7f5830b-4c53-4a55-a641-bc07ef502ab2/resourcegroups/rp-gmsa-rg/providers/microsoft.compute/virtualmachines/rpwinapp01";
                     * string resourceGraphUri = $"https://management.azure.com/{linkId}?api-version=2016-09-01";
                     * ResourceGraphResponse resourcesGraph = await ResilientRestClient.GetAsync<ResourceGraphResponse>(resourceGraphUri, token);
                     */

                    string resourceGraphUri          = "https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2019-04-01";
                    string query                     = $"where id =~ '{alertObj.resourceId}' | project location";
                    Dictionary <string, int> options = new Dictionary <string, int>();
                    options["$skip"] = 0;
                    Dictionary <string, object> resourceObj = new Dictionary <string, object>();

                    resourceObj.Add("subscriptions", subs);
                    resourceObj.Add("query", query);
                    resourceObj.Add("options", options);

                    ResourceGraphResponse resourcesGraph = ResilientRestClient.PostAsync <ResourceGraphResponse>(resourceGraphUri, token, resourceObj).Result;
                    alertObj.location        = resourcesGraph.data.rows[0][0].ToString();
                    alertHistoryObj.location = resourcesGraph.data.rows[0][0].ToString();
                }
                catch (System.Exception)
                {
                    alertObj.location        = "NA";
                    alertHistoryObj.location = "NA";
                    log.LogError($"Unable to get location for {alertObj.resourceId}.  Set default for NA location");
                }

                var collectionId        = GetEnvironmentVariable("CosmosDb_Collection");
                var databaseId          = GetEnvironmentVariable("CosmosDb_Database");
                var collectionHistoryId = GetEnvironmentVariable("CosmosDb_HistoryCollection");

                try
                {
                    ItemResponse <ResourceHealthDto> response = await client.GetContainer(databaseId, collectionId).UpsertItemAsync(alertObj, new PartitionKey(alertObj.resourceId));

                    log.LogInformation("Document created in Cosmos: " + response.StatusCode);
                }
                catch (CosmosException ex)
                {
                    log.LogInformation("error created in Cosmos: " + ex.Message);
                    log.LogInformation("Add Object to Retry Queue: " + ex.Message);
                    // retryQueue.Add(alertObj);
                }

                try
                {
                    ItemResponse <ResourceHealthDto> responseHistory = await client.GetContainer(databaseId, collectionHistoryId).CreateItemAsync(alertHistoryObj, new PartitionKey(alertHistoryObj.resourceId));

                    log.LogInformation("Document created in Cosmos History: " + responseHistory.StatusCode);
                }
                catch (CosmosException ex)
                {
                    log.LogInformation("error created in Cosmos: " + ex.Message);
                    //retryQueue.Add(alertHistoryObj);
                }
            }
            else
            {
                var activitylog = JsonConvert.DeserializeObject <ActivityLogAlert>(requestBody);
                log.LogInformation(activitylog.schemaId);

                var alertObj = CosmosHelper.GetActivityLogAlertDtoMapping(activitylog, log);

                try
                {
                    List <string> subs = new List <string>
                    {
                        alertObj.subscriptionId
                    };
                    string token = AuthHelper.GetTokenAsync().Result;
                    log.LogInformation($"Token Received: {token}");
                    string resourceGraphUri = "https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2018-09-01-preview";
                    string query            = $"where id =~ '{alertObj.resourceId}' | project location, properties.hardwareProfile.vmSize, sku.name ";
                    //, properties.hardwareProfile.vmSize,sku.name";
                    Dictionary <string, int> options = new Dictionary <string, int>();
                    options["$skip"] = 0;
                    Dictionary <string, object> resourceObj = new Dictionary <string, object>();

                    resourceObj.Add("subscriptions", subs);
                    resourceObj.Add("query", query);
                    resourceObj.Add("options", options);

                    ResourceGraphResponse resourcesGraph = ResilientRestClient.PostAsync <ResourceGraphResponse>(resourceGraphUri, token, resourceObj).Result;

                    alertObj.location = resourcesGraph.data.rows[0][0].ToString();

                    if (!(String.IsNullOrEmpty(resourcesGraph.data.rows[0][1])))
                    {
                        alertObj.size = resourcesGraph.data.rows[0][1].ToString();
                    }
                    else
                    {
                        alertObj.size = String.IsNullOrEmpty(resourcesGraph.data.rows[0][2])? "" :resourcesGraph.data.rows[0][2].ToString();
                    }
                }
                catch (System.Exception ex)
                {
                    log.LogError($"error {ex.Message}");

                    alertObj.location = "N/A";
                    alertObj.size     = "N/A";
                    log.LogError($"Unable to get location for {alertObj.resourceId}");

                    log.LogInformation($"Unable to get location for {alertObj.resourceId}");
                    log.LogInformation($"error {ex.Message}");
                }
                log.LogInformation("Resource Subscription: " + alertObj.subscriptionId);
                log.LogInformation("Resource Id: " + alertObj.resourceId);
                log.LogInformation("Resource Status: " + alertObj.alertStatus);
                var collectionId = GetEnvironmentVariable("CosmosDb_Activitylogs");
                var databaseId   = GetEnvironmentVariable("CosmosDb_Database");

                try
                {
                    ItemResponse <ActivityLogDto> response = await client.GetContainer(databaseId, collectionId).UpsertItemAsync(alertObj, new PartitionKey(alertObj.id));

                    log.LogInformation("Document created in Cosmos: " + response.StatusCode);
                }
                catch (CosmosException ex)
                {
                    log.LogInformation("error created in Cosmos: " + ex.Message);
                }
            }

            return(new OkObjectResult("Resource Health Alert Processed"));
        }