From 65cb02535501d3f35250712c8005568182e9dd42 Mon Sep 17 00:00:00 2001 From: Tom Kerkhove Date: Sun, 5 Jul 2020 10:38:41 +0200 Subject: [PATCH] Provide validation rule to verify if resource discovery is configured when metric discovery is used (#1142) * Provide validation rule to verify if resource discovery is configured Signed-off-by: Tom Kerkhove * Improve error message --- .../Validation/RuntimeValidator.cs | 2 +- .../Steps/ResourceDiscoveryValidationStep.cs | 22 ++++++- .../Services/ResourceDiscoveryTests.cs | 6 +- .../ResourceDiscoveryValidationStepTests.cs | 60 +++++++++++++++++-- 4 files changed, 79 insertions(+), 11 deletions(-) diff --git a/src/Promitor.Agents.Scraper/Validation/RuntimeValidator.cs b/src/Promitor.Agents.Scraper/Validation/RuntimeValidator.cs index f80d78b67..81533fb4d 100644 --- a/src/Promitor.Agents.Scraper/Validation/RuntimeValidator.cs +++ b/src/Promitor.Agents.Scraper/Validation/RuntimeValidator.cs @@ -32,7 +32,7 @@ public RuntimeValidator( new ConfigurationPathValidationStep(metricsConfiguration, _validationLogger), new AzureAuthenticationValidationStep(configuration, _validationLogger), new MetricsDeclarationValidationStep(scrapeConfigurationProvider, _validationLogger), - new ResourceDiscoveryValidationStep(runtimeConfiguration.Value.ResourceDiscovery, _validationLogger), + new ResourceDiscoveryValidationStep(runtimeConfiguration.Value.ResourceDiscovery, scrapeConfigurationProvider, _validationLogger), new StatsDMetricSinkValidationStep(runtimeConfiguration, _validationLogger), new PrometheusScrapingEndpointMetricSinkValidationStep(runtimeConfiguration, _validationLogger) }; diff --git a/src/Promitor.Agents.Scraper/Validation/Steps/ResourceDiscoveryValidationStep.cs b/src/Promitor.Agents.Scraper/Validation/Steps/ResourceDiscoveryValidationStep.cs index cd5c4caab..b5dfddd13 100644 --- a/src/Promitor.Agents.Scraper/Validation/Steps/ResourceDiscoveryValidationStep.cs +++ b/src/Promitor.Agents.Scraper/Validation/Steps/ResourceDiscoveryValidationStep.cs @@ -4,19 +4,24 @@ using Microsoft.Extensions.Logging.Abstractions; using Promitor.Agents.Scraper.Configuration; using Promitor.Agents.Scraper.Validation.Interfaces; +using Promitor.Core.Scraping.Configuration.Providers.Interfaces; +using Promitor.Core.Scraping.Configuration.Serialization; namespace Promitor.Agents.Scraper.Validation.Steps { public class ResourceDiscoveryValidationStep : ValidationStep, IValidationStep { + private const string NoDiscoveryConfiguredError = "Resource discovery groups are defined in your metrics configuration, but resource discovery has not been configured in the runtime configuration. Please add a resource discovery configuration for Promitor Scraper runtime."; + private readonly IMetricsDeclarationProvider _metricsDeclarationProvider; private readonly ResourceDiscoveryConfiguration _configuration; - public ResourceDiscoveryValidationStep(ResourceDiscoveryConfiguration configuration) : this(configuration, NullLogger.Instance) + public ResourceDiscoveryValidationStep(ResourceDiscoveryConfiguration configuration, IMetricsDeclarationProvider metricsDeclarationProvider) : this(configuration, metricsDeclarationProvider, NullLogger.Instance) { } - public ResourceDiscoveryValidationStep(ResourceDiscoveryConfiguration configuration, ILogger logger) : base( logger) + public ResourceDiscoveryValidationStep(ResourceDiscoveryConfiguration configuration, IMetricsDeclarationProvider metricsDeclarationProvider, ILogger logger) : base( logger) { + _metricsDeclarationProvider = metricsDeclarationProvider; _configuration = configuration; } @@ -24,8 +29,14 @@ public ResourceDiscoveryValidationStep(ResourceDiscoveryConfiguration configurat public ValidationResult Run() { + var doesDeclareResourceDiscoveryGroups = DetermineIfDiscoveryGroupsAreDefined(); if (_configuration == null) { + if (doesDeclareResourceDiscoveryGroups) + { + return ValidationResult.Failure(ComponentName, new List { NoDiscoveryConfiguredError }); + } + return ValidationResult.Successful(ComponentName); } @@ -42,5 +53,12 @@ public ValidationResult Run() return errorMessages.Any() ? ValidationResult.Failure(ComponentName, errorMessages) : ValidationResult.Successful(ComponentName); } + + private bool DetermineIfDiscoveryGroupsAreDefined() + { + var errorReporter = new ErrorReporter(); + var metricsDeclaration = _metricsDeclarationProvider.Get(applyDefaults: true, errorReporter: errorReporter); + return metricsDeclaration.Metrics.Any(metricDefinition => metricDefinition.ResourceDiscoveryGroups?.Count >= 1); + } } } \ No newline at end of file diff --git a/src/Promitor.Tests.Integration/Services/ResourceDiscoveryTests.cs b/src/Promitor.Tests.Integration/Services/ResourceDiscoveryTests.cs index 7a597d77e..956df8cbd 100644 --- a/src/Promitor.Tests.Integration/Services/ResourceDiscoveryTests.cs +++ b/src/Promitor.Tests.Integration/Services/ResourceDiscoveryTests.cs @@ -39,7 +39,7 @@ public async Task ResourceDiscovery_GetAllPerResourceTypeWithoutFilters_ReturnsE { // Arrange const string resourceDiscoveryGroupName = "no-filter"; - const int expectedResourceCount = 10; + const int expectedResourceCount = 11; var resourceDiscoveryClient = new ResourceDiscoveryClient(Configuration, Logger); // Act @@ -119,7 +119,7 @@ public async Task ResourceDiscovery_GetWithFilterOnTwoSubscriptions_ReturnsExpec { // Arrange const string resourceDiscoveryGroupName = "two-subscriptions-scenario"; - const int expectedResourceCount = 10; + const int expectedResourceCount = 11; var resourceDiscoveryClient = new ResourceDiscoveryClient(Configuration, Logger); // Act @@ -199,7 +199,7 @@ public async Task ResourceDiscovery_GetWithFilterOnTwoRegions_ReturnsExpectedAmo { // Arrange const string resourceDiscoveryGroupName = "two-region-scenario"; - const int expectedResourceCount = 9; + const int expectedResourceCount = 10; var resourceDiscoveryClient = new ResourceDiscoveryClient(Configuration, Logger); // Act diff --git a/src/Promitor.Tests.Unit/Validation/Misc/ResourceDiscoveryValidationStepTests.cs b/src/Promitor.Tests.Unit/Validation/Misc/ResourceDiscoveryValidationStepTests.cs index 193d59db2..0a457d5f9 100644 --- a/src/Promitor.Tests.Unit/Validation/Misc/ResourceDiscoveryValidationStepTests.cs +++ b/src/Promitor.Tests.Unit/Validation/Misc/ResourceDiscoveryValidationStepTests.cs @@ -1,7 +1,11 @@ using System.ComponentModel; +using AutoMapper; using Promitor.Agents.Scraper.Configuration; using Promitor.Agents.Scraper.Validation.Steps; +using Promitor.Core.Scraping.Configuration.Serialization.v1.Mapping; +using Promitor.Tests.Unit.Builders.Metrics.v1; using Promitor.Tests.Unit.Generators.Config; +using Promitor.Tests.Unit.Stubs; using Xunit; namespace Promitor.Tests.Unit.Validation.Misc @@ -9,14 +13,23 @@ namespace Promitor.Tests.Unit.Validation.Misc [Category("Unit")] public class ResourceDiscoveryValidationStepTests { + private readonly IMapper _mapper; + + public ResourceDiscoveryValidationStepTests() + { + var config = new MapperConfiguration(c => c.AddProfile()); + _mapper = config.CreateMapper(); + } + [Fact] public void Validate_ResourceDiscoveryIsFullyConfigured_Success() { // Arrange + var metricsDeclarationProvider = GetMetricDeclarationProvider(); var resourceDiscoveryConfiguration = CreateRuntimeConfiguration(); // Act - var azureAuthenticationValidationStep = new ResourceDiscoveryValidationStep(resourceDiscoveryConfiguration); + var azureAuthenticationValidationStep = new ResourceDiscoveryValidationStep(resourceDiscoveryConfiguration, metricsDeclarationProvider); var validationResult = azureAuthenticationValidationStep.Run(); // Assert @@ -27,26 +40,44 @@ public void Validate_ResourceDiscoveryIsFullyConfigured_Success() public void Validate_ResourceDiscoveryIsNotConfigured_Success() { // Arrange + var metricsDeclarationProvider = GetMetricDeclarationProvider(); ResourceDiscoveryConfiguration resourceDiscoveryConfiguration = null; // Act // ReSharper disable once ExpressionIsAlwaysNull - var azureAuthenticationValidationStep = new ResourceDiscoveryValidationStep(resourceDiscoveryConfiguration); + var azureAuthenticationValidationStep = new ResourceDiscoveryValidationStep(resourceDiscoveryConfiguration, metricsDeclarationProvider); var validationResult = azureAuthenticationValidationStep.Run(); // Assert Assert.True(validationResult.IsSuccessful); } + [Fact] + public void Validate_ResourceDiscoveryIsNotConfiguredButMetricWithDiscoveryIsDefined_Fails() + { + // Arrange + var metricsDeclarationProvider = GetMetricDeclarationProvider(useDiscoveryGroup: true); + ResourceDiscoveryConfiguration resourceDiscoveryConfiguration = null; + + // Act + // ReSharper disable once ExpressionIsAlwaysNull + var azureAuthenticationValidationStep = new ResourceDiscoveryValidationStep(resourceDiscoveryConfiguration, metricsDeclarationProvider); + var validationResult = azureAuthenticationValidationStep.Run(); + + // Assert + Assert.False(validationResult.IsSuccessful); + } + [Fact] public void Validate_StatsDWithNegativePort_Fails() { // Arrange + var metricsDeclarationProvider = GetMetricDeclarationProvider(); var resourceDiscoveryConfiguration = CreateRuntimeConfiguration(); resourceDiscoveryConfiguration.Port = -1; // Act - var azureAuthenticationValidationStep = new ResourceDiscoveryValidationStep(resourceDiscoveryConfiguration); + var azureAuthenticationValidationStep = new ResourceDiscoveryValidationStep(resourceDiscoveryConfiguration, metricsDeclarationProvider); var validationResult = azureAuthenticationValidationStep.Run(); // Assert @@ -57,11 +88,12 @@ public void Validate_StatsDWithNegativePort_Fails() public void Validate_StatsDWithPortZero_Fails() { // Arrange + var metricsDeclarationProvider = GetMetricDeclarationProvider(); var resourceDiscoveryConfiguration = CreateRuntimeConfiguration(); resourceDiscoveryConfiguration.Port = 0; // Act - var azureAuthenticationValidationStep = new ResourceDiscoveryValidationStep(resourceDiscoveryConfiguration); + var azureAuthenticationValidationStep = new ResourceDiscoveryValidationStep(resourceDiscoveryConfiguration, metricsDeclarationProvider); var validationResult = azureAuthenticationValidationStep.Run(); // Assert @@ -75,11 +107,12 @@ public void Validate_StatsDWithPortZero_Fails() public void Validate_NoHostIsConfigured_Fails(string host) { // Arrange + var metricsDeclarationProvider = GetMetricDeclarationProvider(); var resourceDiscoveryConfiguration = CreateRuntimeConfiguration(); resourceDiscoveryConfiguration.Host = host; // Act - var azureAuthenticationValidationStep = new ResourceDiscoveryValidationStep(resourceDiscoveryConfiguration); + var azureAuthenticationValidationStep = new ResourceDiscoveryValidationStep(resourceDiscoveryConfiguration, metricsDeclarationProvider); var validationResult = azureAuthenticationValidationStep.Run(); // Assert @@ -92,5 +125,22 @@ private ResourceDiscoveryConfiguration CreateRuntimeConfiguration() return bogusRuntimeConfiguration.ResourceDiscovery; } + + private MetricsDeclarationProviderStub GetMetricDeclarationProvider(bool useDiscoveryGroup=false) + { + var metricsDeclarationBuilder = MetricsDeclarationBuilder.WithMetadata() + .WithApiManagementMetric(locationName: string.Empty); + + if (useDiscoveryGroup) + { + metricsDeclarationBuilder.WithApiManagementMetric(resourceDiscoveryGroupName: "hello-cloud"); + } + + var rawDeclaration = metricsDeclarationBuilder + .Build(_mapper); + + var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, _mapper); + return metricsDeclarationProvider; + } } } \ No newline at end of file