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}"); }
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); }); }
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")); }