Skip to content

Commit 2778e84

Browse files
feat: Adding ability to define a custom AzureEnvironment. (#2579)
* custom cloud support - addressing review comments * coderefactor * remove unused declaratives * Add unit test + address review comments * refactor * add interface for cloud + endpoints * refactor from codefactor comment * cleanup * Add Log Analytics Endpoint for Custom Cloud * add unit test + fix code quality failure * code factor * code quality fix --------- Co-authored-by: Suraiya Hameed <[email protected]>
1 parent 22b0792 commit 2778e84

31 files changed

+1129
-259
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
using System.Collections.Generic;
2+
using Promitor.Core.Configuration;
3+
using Promitor.Core.Extensions;
24
using Promitor.Core.Serialization.Enum;
35

46
namespace Promitor.Agents.ResourceDiscovery.Configuration
57
{
6-
public class AzureLandscape
8+
public class AzureLandscape : IAzureCloudEndpoints
79
{
810
public string TenantId { get; set; }
911
public List<string> Subscriptions { get; set; }
1012
public AzureCloud Cloud { get; set; } = AzureCloud.Global;
13+
public AzureEndpoints Endpoints { get; set; }
1114
}
1215
}

src/Promitor.Agents.ResourceDiscovery/Graph/AzureResourceGraph.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,8 @@ private async Task OpenConnectionAsync()
267267

268268
private async Task<ResourceGraphClient> CreateClientAsync()
269269
{
270-
var azureEnvironment = _resourceDeclarationMonitor.CurrentValue.AzureLandscape.Cloud.GetAzureEnvironment();
271-
var azureAuthorityHost = _resourceDeclarationMonitor.CurrentValue.AzureLandscape.Cloud.GetAzureAuthorityHost();
270+
var azureEnvironment = _resourceDeclarationMonitor.CurrentValue.AzureLandscape.GetAzureEnvironment();
271+
var azureAuthorityHost = _resourceDeclarationMonitor.CurrentValue.AzureLandscape.GetAzureAuthorityHost();
272272

273273
var credentials = await AzureAuthenticationFactory.GetTokenCredentialsAsync(azureEnvironment.ManagementEndpoint, TenantId, _azureAuthenticationInfo, azureAuthorityHost);
274274
var resourceManagerBaseUri = new Uri(azureEnvironment.ResourceManagerEndpoint);

src/Promitor.Agents.ResourceDiscovery/Validation/Steps/AzureLandscapeValidationStep.cs

+46-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,13 @@ public ValidationResult Run()
3434
{
3535
errorMessages.Add("No Azure cloud was configured");
3636
}
37-
38-
if (_azureLandscape.Subscriptions == null || _azureLandscape.Subscriptions.Any() == false)
37+
38+
if (_azureLandscape.Cloud == AzureCloud.Custom)
39+
{
40+
errorMessages.AddRange(ValidateCustomCloud());
41+
}
42+
43+
if (_azureLandscape.Subscriptions == null || _azureLandscape.Subscriptions.Count == 0)
3944
{
4045
errorMessages.Add("No subscription id(s) were configured to query");
4146
}
@@ -54,5 +59,44 @@ public ValidationResult Run()
5459

5560
return errorMessages.Any() ? ValidationResult.Failure(ComponentName, errorMessages) : ValidationResult.Successful(ComponentName);
5661
}
62+
63+
private IEnumerable<string> ValidateCustomCloud()
64+
{
65+
var errorMessages = new List<string>();
66+
67+
if(_azureLandscape.Endpoints == null)
68+
{
69+
errorMessages.Add("Endpoints are not configured for Azure Custom cloud");
70+
}
71+
else
72+
{
73+
if (string.IsNullOrWhiteSpace(_azureLandscape.Endpoints.AuthenticationEndpoint))
74+
{
75+
errorMessages.Add("Azure Custom cloud authentication endpoint was not configured to query");
76+
}
77+
if (string.IsNullOrWhiteSpace(_azureLandscape.Endpoints.ResourceManagerEndpoint))
78+
{
79+
errorMessages.Add("Azure Custom cloud resource management endpoint was not configured to query");
80+
}
81+
if (string.IsNullOrWhiteSpace(_azureLandscape.Endpoints.ManagementEndpoint))
82+
{
83+
errorMessages.Add("Azure Custom cloud service management endpoint was not configured to query");
84+
}
85+
if (string.IsNullOrWhiteSpace(_azureLandscape.Endpoints.GraphEndpoint))
86+
{
87+
errorMessages.Add("Azure Custom cloud graph endpoint was not configured to query");
88+
}
89+
if (string.IsNullOrWhiteSpace(_azureLandscape.Endpoints.StorageEndpointSuffix))
90+
{
91+
errorMessages.Add("Azure Custom cloud storage service url suffix was not configured to query");
92+
}
93+
if (string.IsNullOrWhiteSpace(_azureLandscape.Endpoints.KeyVaultSuffix))
94+
{
95+
errorMessages.Add("Azure Custom cloud Key Vault service url suffix was not configured to query");
96+
}
97+
}
98+
99+
return errorMessages;
100+
}
57101
}
58102
}

src/Promitor.Agents.Scraper/AzureMonitorClientFactory.cs

+13-11
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
using Promitor.Core.Extensions;
88
using Promitor.Core.Metrics.Interfaces;
99
using Promitor.Core.Metrics.Sinks;
10-
using Promitor.Core.Serialization.Enum;
10+
using Promitor.Core.Scraping.Configuration.Model;
1111
using Promitor.Integrations.Azure.Authentication;
1212
using Promitor.Integrations.AzureMonitor;
1313
using Promitor.Integrations.AzureMonitor.Configuration;
@@ -21,7 +21,7 @@ public class AzureMonitorClientFactory
2121
/// <summary>
2222
/// Provides an Azure Monitor client
2323
/// </summary>
24-
/// <param name="cloud">Name of the Azure cloud to interact with</param>
24+
/// <param name="azureMetadata">Azure metadata information</param>
2525
/// <param name="tenantId">Id of the tenant that owns the Azure subscription</param>
2626
/// <param name="subscriptionId">Id of the Azure subscription</param>
2727
/// <param name="metricSinkWriter">Writer to send metrics to all configured sinks</param>
@@ -31,19 +31,21 @@ public class AzureMonitorClientFactory
3131
/// <param name="azureMonitorIntegrationConfiguration">Options for Azure Monitor integration</param>
3232
/// <param name="azureMonitorLoggingConfiguration">Options for Azure Monitor logging</param>
3333
/// <param name="loggerFactory">Factory to create loggers with</param>
34-
public IAzureMonitorClient CreateIfNotExists(AzureCloud cloud, string tenantId, string subscriptionId, MetricSinkWriter metricSinkWriter, IAzureScrapingSystemMetricsPublisher azureScrapingSystemMetricsPublisher, IMemoryCache resourceMetricDefinitionMemoryCache, IConfiguration configuration, IOptions<AzureMonitorIntegrationConfiguration> azureMonitorIntegrationConfiguration, IOptions<AzureMonitorLoggingConfiguration> azureMonitorLoggingConfiguration, ILoggerFactory loggerFactory)
35-
{
34+
public IAzureMonitorClient CreateIfNotExists(AzureMetadata azureMetadata, string tenantId, string subscriptionId, MetricSinkWriter metricSinkWriter, IAzureScrapingSystemMetricsPublisher azureScrapingSystemMetricsPublisher, IMemoryCache resourceMetricDefinitionMemoryCache, IConfiguration configuration, IOptions<AzureMonitorIntegrationConfiguration> azureMonitorIntegrationConfiguration, IOptions<AzureMonitorLoggingConfiguration> azureMonitorLoggingConfiguration, ILoggerFactory loggerFactory)
35+
{
3636
if (_azureMonitorClients.TryGetValue(subscriptionId, out var value))
3737
{
3838
return value;
3939
}
40-
4140
var useAzureMonitorSdk = azureMonitorIntegrationConfiguration.Value.UseAzureMonitorSdk;
4241
IAzureMonitorClient azureMonitorClient;
43-
if (useAzureMonitorSdk) {
44-
azureMonitorClient = CreateNewAzureMonitorQueryClient(cloud, tenantId, subscriptionId, metricSinkWriter, azureScrapingSystemMetricsPublisher, resourceMetricDefinitionMemoryCache, configuration, azureMonitorIntegrationConfiguration, azureMonitorLoggingConfiguration, loggerFactory);
45-
} else {
46-
azureMonitorClient = CreateNewLegacyAzureMonitorClient(cloud.GetAzureEnvironment(), tenantId, subscriptionId, metricSinkWriter, azureScrapingSystemMetricsPublisher, resourceMetricDefinitionMemoryCache, configuration, azureMonitorIntegrationConfiguration, azureMonitorLoggingConfiguration, loggerFactory);
42+
if (useAzureMonitorSdk)
43+
{
44+
azureMonitorClient = CreateNewAzureMonitorQueryClient(azureMetadata, tenantId, subscriptionId, metricSinkWriter, azureScrapingSystemMetricsPublisher, resourceMetricDefinitionMemoryCache, configuration, azureMonitorIntegrationConfiguration, azureMonitorLoggingConfiguration, loggerFactory);
45+
}
46+
else
47+
{
48+
azureMonitorClient = CreateNewLegacyAzureMonitorClient(azureMetadata.GetAzureEnvironment(), tenantId, subscriptionId, metricSinkWriter, azureScrapingSystemMetricsPublisher, resourceMetricDefinitionMemoryCache, configuration, azureMonitorIntegrationConfiguration, azureMonitorLoggingConfiguration, loggerFactory);
4749
}
4850
_azureMonitorClients.TryAdd(subscriptionId, azureMonitorClient);
4951

@@ -57,10 +59,10 @@ private static LegacyAzureMonitorClient CreateNewLegacyAzureMonitorClient(AzureE
5759
return azureMonitorClientLegacy;
5860
}
5961

60-
private static AzureMonitorQueryClient CreateNewAzureMonitorQueryClient(AzureCloud cloud, string tenantId, string subscriptionId, MetricSinkWriter metricSinkWriter, IAzureScrapingSystemMetricsPublisher azureScrapingSystemMetricsPublisher, IMemoryCache resourceMetricDefinitionMemoryCache, IConfiguration configuration, IOptions<AzureMonitorIntegrationConfiguration> azureMonitorIntegrationConfiguration, IOptions<AzureMonitorLoggingConfiguration> azureMonitorLoggingConfiguration, ILoggerFactory loggerFactory)
62+
private static AzureMonitorQueryClient CreateNewAzureMonitorQueryClient(AzureMetadata azureMetadata, string tenantId, string subscriptionId, MetricSinkWriter metricSinkWriter, IAzureScrapingSystemMetricsPublisher azureScrapingSystemMetricsPublisher, IMemoryCache resourceMetricDefinitionMemoryCache, IConfiguration configuration, IOptions<AzureMonitorIntegrationConfiguration> azureMonitorIntegrationConfiguration, IOptions<AzureMonitorLoggingConfiguration> azureMonitorLoggingConfiguration, ILoggerFactory loggerFactory)
6163
{
6264
var azureCredentials = AzureAuthenticationFactory.GetConfiguredAzureAuthentication(configuration);
63-
var azureMonitorQueryClient = new AzureMonitorQueryClient(cloud, tenantId, subscriptionId, azureCredentials, metricSinkWriter, azureScrapingSystemMetricsPublisher, resourceMetricDefinitionMemoryCache, loggerFactory, azureMonitorIntegrationConfiguration, azureMonitorLoggingConfiguration);
65+
var azureMonitorQueryClient = new AzureMonitorQueryClient(azureMetadata, tenantId, subscriptionId, azureCredentials, metricSinkWriter, azureScrapingSystemMetricsPublisher, resourceMetricDefinitionMemoryCache, loggerFactory, azureMonitorIntegrationConfiguration, azureMonitorLoggingConfiguration);
6466
return azureMonitorQueryClient;
6567
}
6668
}

src/Promitor.Agents.Scraper/Docs/Open-Api.xml

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Promitor.Agents.Scraper/Extensions/IServiceCollectionExtensions.cs

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ public static IServiceCollection DefineDependencies(this IServiceCollection serv
119119

120120
services.AddSingleton<IDeserializer<MetricsDeclarationV1>, V1Deserializer>();
121121
services.AddSingleton<IDeserializer<AzureMetadataV1>, AzureMetadataDeserializer>();
122+
services.AddSingleton<IDeserializer<AzureEndpointsV1>, AzureEndpointsDeserializer>();
122123
services.AddSingleton<IDeserializer<MetricDefaultsV1>, MetricDefaultsDeserializer>();
123124
services.AddSingleton<IDeserializer<MetricDefinitionV1>, MetricDefinitionDeserializer>();
124125
services.AddSingleton<IDeserializer<AggregationV1>, AggregationDeserializer>();

src/Promitor.Agents.Scraper/Scheduling/ResourcesScrapingJob.cs

+9-9
Original file line numberDiff line numberDiff line change
@@ -285,14 +285,14 @@ private async Task ScrapeMetricBatched(BatchScrapeDefinition<IAzureResourceDefin
285285
try
286286
{
287287
var resourceSubscriptionId = batchScrapeDefinition.ScrapeDefinitionBatchProperties.SubscriptionId;
288-
var azureMonitorClient = _azureMonitorClientFactory.CreateIfNotExists(_metricsDeclaration.AzureMetadata.Cloud, _metricsDeclaration.AzureMetadata.TenantId,
288+
var azureMonitorClient = _azureMonitorClientFactory.CreateIfNotExists(_metricsDeclaration.AzureMetadata, _metricsDeclaration.AzureMetadata.TenantId,
289289
resourceSubscriptionId, _metricSinkWriter, _azureScrapingSystemMetricsPublisher, _resourceMetricDefinitionMemoryCache, _configuration,
290290
_azureMonitorIntegrationConfiguration, _azureMonitorLoggingConfiguration, _loggerFactory);
291-
var azureEnvironent = _metricsDeclaration.AzureMetadata.Cloud.GetAzureEnvironment();
291+
var azureEnvironment = _metricsDeclaration.AzureMetadata.GetAzureEnvironment();
292292

293-
var tokenCredential = AzureAuthenticationFactory.GetTokenCredential(azureEnvironent.ManagementEndpoint, _metricsDeclaration.AzureMetadata.TenantId,
294-
AzureAuthenticationFactory.GetConfiguredAzureAuthentication(_configuration), new Uri(_metricsDeclaration.AzureMetadata.Cloud.GetAzureEnvironment().AuthenticationEndpoint));
295-
var logAnalyticsClient = new LogAnalyticsClient(_loggerFactory, azureEnvironent, tokenCredential);
293+
var tokenCredential = AzureAuthenticationFactory.GetTokenCredential(azureEnvironment.ManagementEndpoint, _metricsDeclaration.AzureMetadata.TenantId,
294+
AzureAuthenticationFactory.GetConfiguredAzureAuthentication(_configuration), new Uri (_metricsDeclaration.AzureMetadata.GetAzureEnvironment().AuthenticationEndpoint));
295+
var logAnalyticsClient = new LogAnalyticsClient(_loggerFactory, _metricsDeclaration.AzureMetadata.GetLogAnalyticsEndpoint(), tokenCredential);
296296

297297
var scraper = _metricScraperFactory.CreateScraper(batchScrapeDefinition.ScrapeDefinitionBatchProperties.ResourceType, _metricSinkWriter, _azureScrapingSystemMetricsPublisher, azureMonitorClient, logAnalyticsClient);
298298

@@ -313,15 +313,15 @@ private async Task ScrapeMetric(ScrapeDefinition<IAzureResourceDefinition> scrap
313313
var resourceSubscriptionId = !string.IsNullOrWhiteSpace(scrapeDefinition.Resource.SubscriptionId)
314314
? scrapeDefinition.Resource.SubscriptionId
315315
: _metricsDeclaration.AzureMetadata.SubscriptionId;
316-
var azureEnvironent = _metricsDeclaration.AzureMetadata.Cloud.GetAzureEnvironment();
316+
var azureEnvironent = _metricsDeclaration.AzureMetadata.GetAzureEnvironment();
317317
Logger.LogInformation("Parsed SDK Config {UseAzureMonitorSdk}", _azureMonitorIntegrationConfiguration.Value.UseAzureMonitorSdk);
318-
var azureMonitorClient = _azureMonitorClientFactory.CreateIfNotExists(_metricsDeclaration.AzureMetadata.Cloud, _metricsDeclaration.AzureMetadata.TenantId,
318+
var azureMonitorClient = _azureMonitorClientFactory.CreateIfNotExists(_metricsDeclaration.AzureMetadata, _metricsDeclaration.AzureMetadata.TenantId,
319319
resourceSubscriptionId, _metricSinkWriter, _azureScrapingSystemMetricsPublisher, _resourceMetricDefinitionMemoryCache, _configuration,
320320
_azureMonitorIntegrationConfiguration, _azureMonitorLoggingConfiguration, _loggerFactory);
321321

322322
var tokenCredential = AzureAuthenticationFactory.GetTokenCredential(azureEnvironent.ManagementEndpoint, _metricsDeclaration.AzureMetadata.TenantId,
323-
AzureAuthenticationFactory.GetConfiguredAzureAuthentication(_configuration), new Uri(_metricsDeclaration.AzureMetadata.Cloud.GetAzureEnvironment().AuthenticationEndpoint));
324-
var logAnalyticsClient = new LogAnalyticsClient(_loggerFactory, azureEnvironent, tokenCredential);
323+
AzureAuthenticationFactory.GetConfiguredAzureAuthentication(_configuration), new Uri(_metricsDeclaration.AzureMetadata.GetAzureEnvironment().AuthenticationEndpoint));
324+
var logAnalyticsClient = new LogAnalyticsClient(_loggerFactory, _metricsDeclaration.AzureMetadata.GetLogAnalyticsEndpoint(), tokenCredential);
325325

326326
var scraper = _metricScraperFactory.CreateScraper(scrapeDefinition.Resource.ResourceType, _metricSinkWriter, _azureScrapingSystemMetricsPublisher, azureMonitorClient, logAnalyticsClient);
327327

0 commit comments

Comments
 (0)