public static async Task Run(string myQueueItem, CloudTable invalidResourceTable, TraceWriter log) { log.Info($"C# Queue trigger function triggered: {myQueueItem}"); ResourceItem updateItem = JsonConvert.DeserializeObject <ResourceItem>(myQueueItem); ResourceManagerService resourceManager = null; try { string token = await AuthenticationService.GetAccessTokenAsync(); resourceManager = new ResourceManagerService(token); } catch (Exception ex) { log.Error("Unable to connect to the ARM API, Message: " + ex.Message); } try { await resourceManager.UpdateResource(updateItem); } catch (Exception ex) { log.Error(updateItem.Id + " failed with: " + ex.Message); InvalidTagResource matchingInvalidResource = null; var invalidTagResourcesQuery = await invalidResourceTable.ExecuteQuerySegmentedAsync(new TableQuery <InvalidTagResource>(), null); if (invalidTagResourcesQuery.Results != null) { matchingInvalidResource = invalidTagResourcesQuery.Results.Where(x => x.Type == updateItem.Type).FirstOrDefault(); } if (matchingInvalidResource == null) { InvalidTagResource invalidItem = new InvalidTagResource { Type = updateItem.Type, Message = ex.Message, RowKey = Guid.NewGuid().ToString(), PartitionKey = updateItem.Subscription }; TableOperation insertOperation = TableOperation.InsertOrReplace(invalidItem); await invalidResourceTable.ExecuteAsync(insertOperation); } } }
public static async Task Run([QueueTrigger("resources-to-tag", Connection = "AzureWebJobsStorage"), Disable("true")] string myQueueItem, [Table("InvalidTagResources")] CloudTable invalidResourceTable, TraceWriter log) { log.Info($"C# Queue trigger function triggered: {myQueueItem}"); ResourceItem updateItem = JsonConvert.DeserializeObject <ResourceItem>(myQueueItem); TokenCredentials tokenCredential; if (Environment.GetEnvironmentVariable("MSI_ENDPOINT") == null) { log.Info("Using service principal"); string appId = Environment.GetEnvironmentVariable("appId"); string appSecret = Environment.GetEnvironmentVariable("appSecret"); string tenantId = Environment.GetEnvironmentVariable("tenantId"); tokenCredential = AuthenticationService.GetAccessToken(appId, appSecret, tenantId); } else { log.Info("Using MSI"); var azureServiceTokenProvider = new AzureServiceTokenProvider(); string token = await azureServiceTokenProvider.GetAccessTokenAsync("https://management.core.windows.net/"); tokenCredential = new TokenCredentials(token); } var client = new ResourceManagementClient(tokenCredential); client.SubscriptionId = updateItem.Subscription; GenericResourceInner resource = null; try { resource = await client.Resources.GetByIdAsync(updateItem.Id, updateItem.ApiVersion); resource.Tags = updateItem.Tags; resource.Properties = null; // some resource types support PATCH operations ONLY on tags. await client.Resources.UpdateByIdAsync(updateItem.Id, updateItem.ApiVersion, resource); } catch (Exception ex) { if (resource == null) { log.Error("Failed to get resource: " + updateItem.Id); log.Error("Error is: " + ex.Message); } else { log.Error(resource.Id + " failed with: " + ex.Message); } InvalidTagResource matchingInvalidResource = null; var invalidTagResourcesQuery = await invalidResourceTable.ExecuteQuerySegmentedAsync(new TableQuery <InvalidTagResource>(), null); if (invalidTagResourcesQuery.Results != null) { matchingInvalidResource = invalidTagResourcesQuery.Results.Where(x => x.Type == updateItem.Type).FirstOrDefault(); } if (matchingInvalidResource == null) { InvalidTagResource invalidItem = new InvalidTagResource { Type = updateItem.Type, Message = ex.Message, RowKey = Guid.NewGuid().ToString(), PartitionKey = updateItem.Subscription }; TableOperation insertOperation = TableOperation.InsertOrReplace(invalidItem); await invalidResourceTable.ExecuteAsync(insertOperation); } } }
static async Task ProcessResourceGroups(IEnumerable <string> requiredTagsList, IEnumerable <ResourceGroupInner> resourceGroups, List <InvalidTagResource> invalidTypes, string subscriptionId, AuditStats stats) { foreach (ResourceGroupInner rg in resourceGroups) { _log.Info("*** Resource Group: " + rg.Name); Dictionary <string, string> requiredRgTags = new Dictionary <string, string>(); foreach (string tagKey in requiredTagsList) { if (rg.Tags != null && rg.Tags.ContainsKey(tagKey)) { requiredRgTags.Add(tagKey, rg.Tags[tagKey]); } } if (requiredRgTags.Count != requiredTagsList.Count()) { _log.Warning("Resource group: " + rg.Name + " does not have required tags."); stats.ResourceGroupsSkipped += 1; } else { IEnumerable <GenericResourceInner> resources = await _client.Resources.ListByResourceGroupAsync(rg.Name); stats.ResourceItemsTotal = resources.Count(); foreach (var resource in resources) { // InvalidTagResource invalidResourceMatch = invalidTagResourcesQuery.Results.Where(x => x.Type == resource.Type).FirstOrDefault(); InvalidTagResource invalidType = invalidTypes.Where(x => x.Type == resource.Type).FirstOrDefault(); if (invalidType == null) { string apiVersion; try { apiVersion = await GetApiVersion(_client, resource.Type); } catch (Exception ex) { _log.Error(ex.Message); break; } var result = SetTags(resource.Tags, requiredRgTags); if (result.Count > 0) { stats.ResourceItemsWithUpdates += 1; resource.Tags = result; ResourceItem newItem = new ResourceItem { Id = resource.Id, ApiVersion = apiVersion, Location = resource.Location, Tags = resource.Tags, Type = resource.Type, Subscription = subscriptionId }; string messageText = JsonConvert.SerializeObject(newItem); _outQueue.Add(messageText); _log.Info("Requesting tags for: " + resource.Id); } else { stats.ResourceItemsSkipped += 1; } } else { _log.Warning("Item type does not support tagging: " + resource.Type); stats.ResourceItemsSkipped += 1; } } } } }