From 66072d7b264ce7f31689d37040df85bdce0f5956 Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Fri, 16 Oct 2020 15:30:51 +0200 Subject: [PATCH 01/10] Support Azure Kubernetes Service (AKS) (#333) --- docs/configuration/v2.x/metrics/index.md | 1 + docs/configuration/v2.x/metrics/kuberbetes.md | 36 +++++ .../Graph/ResourceDiscoveryFactory.cs | 2 + .../ResourceTypes/KubernetesDiscoveryQuery.cs | 21 +++ .../Factories/MetricValidatorFactory.cs | 2 + .../KubernetesMetricValidator.cs | 25 ++++ src/Promitor.Core.Contracts/ResourceType.cs | 3 +- .../KubernetesResourceDefinition.cs | 13 ++ .../Core/AzureResourceDeserializerFactory.cs | 3 + .../v1/Mapping/V1MappingProfile.cs | 2 + .../ResourceTypes/KubernetesResourceV1.cs | 13 ++ .../v1/Providers/KubernetesDeserializer.cs | 14 ++ .../Factories/MetricScraperFactory.cs | 2 + .../ResourceTypes/KubernetesScraper.cs | 22 +++ .../Metrics/v1/MetricsDeclarationBuilder.cs | 17 +++ .../Providers/KubernetesDeserializerTests.cs | 45 ++++++ ...sMetricsDeclarationValidationStepsTests.cs | 132 ++++++++++++++++++ 17 files changed, 352 insertions(+), 1 deletion(-) create mode 100644 docs/configuration/v2.x/metrics/kuberbetes.md create mode 100644 src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/KubernetesDiscoveryQuery.cs create mode 100644 src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/KubernetesMetricValidator.cs create mode 100644 src/Promitor.Core.Contracts/ResourceTypes/KubernetesResourceDefinition.cs create mode 100644 src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/KubernetesResourceV1.cs create mode 100644 src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/KubernetesDeserializer.cs create mode 100644 src/Promitor.Core.Scraping/ResourceTypes/KubernetesScraper.cs create mode 100644 src/Promitor.Tests.Unit/Serialization/v1/Providers/KubernetesDeserializerTests.cs create mode 100644 src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/KubernetesMetricsDeclarationValidationStepsTests.cs diff --git a/docs/configuration/v2.x/metrics/index.md b/docs/configuration/v2.x/metrics/index.md index af3c0b444..edd10d296 100644 --- a/docs/configuration/v2.x/metrics/index.md +++ b/docs/configuration/v2.x/metrics/index.md @@ -134,6 +134,7 @@ We also provide a simplified way to scrape the following Azure resources: - [Azure IoT Hub](iot-hub) - [Azure IoT Hub Device Provisioning Service (DPS)](iot-hub-device-provisioning-service) - [Azure Key Vault](key-vault) +- [Azure Kubernetes Service](kubernetes) - [Azure Logic Apps](logic-apps) - [Azure Network Gateway](network-gateway) - [Azure Network Interface](network-interface) diff --git a/docs/configuration/v2.x/metrics/kuberbetes.md b/docs/configuration/v2.x/metrics/kuberbetes.md new file mode 100644 index 000000000..33466dd65 --- /dev/null +++ b/docs/configuration/v2.x/metrics/kuberbetes.md @@ -0,0 +1,36 @@ +--- +layout: default +title: Azure Kubernetes Service Declaration +--- + +## Azure Kubernetes Service + +![Availability Badge](https://img.shields.io/badge/Available%20Starting-v1.6-green.svg)![Resource Discovery Support Badge](https://img.shields.io/badge/Support%20for%20Resource%20Discovery-Yes-green.svg) + +You can declare to scrape an Azure Kubernetes Service (AKS) +via the `Kubernetes` resource type. + +The following fields need to be provided: + +- `clusterName` - The name of the Azure Kubernetes Service + +All supported metrics are documented in the official [Azure Monitor documentation](https://docs.microsoft.com/en-us/azure/azure-monitor/platform/metrics-supported#microsoftcontainerservicemanagedclusters). + +Example: + +```yaml +name: azure_kubernetes_available_cpu_cores +description: "Available CPU cores in cluster" +resourceType: Kubernetes +azureMetricConfiguration: + metricName: kube_node_status_allocatable_cpu_cores + aggregation: + type: Average +resources: +- clusterName: promitor-aks +``` + + +[← back to metrics declarations](/configuration/v2.x/metrics)
+[← back to introduction](/) + diff --git a/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceDiscoveryFactory.cs b/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceDiscoveryFactory.cs index 78a83a5cd..7dc83cf9d 100644 --- a/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceDiscoveryFactory.cs +++ b/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceDiscoveryFactory.cs @@ -34,6 +34,8 @@ public static ResourceDiscoveryQuery UseResourceDiscoveryFor(ResourceType resour return new IoTHubDiscoveryQuery(); case ResourceType.KeyVault: return new KeyVaultDiscoveryQuery(); + case ResourceType.Kubernetes: + return new KubernetesDiscoveryQuery(); case ResourceType.LogicApp: return new LogicAppDiscoveryQuery(); case ResourceType.NetworkGateway: diff --git a/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/KubernetesDiscoveryQuery.cs b/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/KubernetesDiscoveryQuery.cs new file mode 100644 index 000000000..e9ea5bfe7 --- /dev/null +++ b/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/KubernetesDiscoveryQuery.cs @@ -0,0 +1,21 @@ +using GuardNet; +using Newtonsoft.Json.Linq; +using Promitor.Core.Contracts; +using Promitor.Core.Contracts.ResourceTypes; + +namespace Promitor.Agents.ResourceDiscovery.Graph.ResourceTypes +{ + public class KubernetesDiscoveryQuery : ResourceDiscoveryQuery + { + public override string[] ResourceTypes => new[] { "Microsoft.ContainerService/managedClusters" }; + public override string[] ProjectedFieldNames => new[] { "subscriptionId", "resourceGroup", "type", "name" }; + + public override AzureResourceDefinition ParseResults(JToken resultRowEntry) + { + Guard.NotNull(resultRowEntry, nameof(resultRowEntry)); + + var resource = new KubernetesResourceDefinition(resultRowEntry[0]?.ToString(), resultRowEntry[1]?.ToString(), resultRowEntry[3]?.ToString()); + return resource; + } + } +} diff --git a/src/Promitor.Agents.Scraper/Validation/Factories/MetricValidatorFactory.cs b/src/Promitor.Agents.Scraper/Validation/Factories/MetricValidatorFactory.cs index 65cba4146..b27aa69b3 100644 --- a/src/Promitor.Agents.Scraper/Validation/Factories/MetricValidatorFactory.cs +++ b/src/Promitor.Agents.Scraper/Validation/Factories/MetricValidatorFactory.cs @@ -41,6 +41,8 @@ internal static IMetricValidator GetValidatorFor(ResourceType resourceType) return new IoTHubMetricValidator(); case ResourceType.KeyVault: return new KeyVaultMetricValidator(); + case ResourceType.Kubernetes: + return new KubernetesMetricValidator(); case ResourceType.LogicApp: return new LogicAppMetricValidator(); case ResourceType.NetworkGateway: diff --git a/src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/KubernetesMetricValidator.cs b/src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/KubernetesMetricValidator.cs new file mode 100644 index 000000000..bcbfa1ac6 --- /dev/null +++ b/src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/KubernetesMetricValidator.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Linq; +using GuardNet; +using Promitor.Core.Scraping.Configuration.Model.Metrics; +using Promitor.Agents.Scraper.Validation.MetricDefinitions.Interfaces; +using Promitor.Core.Contracts.ResourceTypes; + +namespace Promitor.Agents.Scraper.Validation.MetricDefinitions.ResourceTypes +{ + internal class KubernetesMetricValidator : IMetricValidator + { + public IEnumerable Validate(MetricDefinition metricDefinition) + { + Guard.NotNull(metricDefinition, nameof(metricDefinition)); + + foreach (var resourceDefinition in metricDefinition.Resources.Cast()) + { + if (string.IsNullOrWhiteSpace(resourceDefinition.ClusterName)) + { + yield return "No Azure Kubernetes Service name is configured"; + } + } + } + } +} \ No newline at end of file diff --git a/src/Promitor.Core.Contracts/ResourceType.cs b/src/Promitor.Core.Contracts/ResourceType.cs index 1b84d5383..734545f6c 100644 --- a/src/Promitor.Core.Contracts/ResourceType.cs +++ b/src/Promitor.Core.Contracts/ResourceType.cs @@ -31,6 +31,7 @@ public enum ResourceType EventHubs = 26, ExpressRouteCircuit = 27, ApplicationGateway = 28, - NetworkGateway = 29 + NetworkGateway = 29, + Kubernetes = 30 } } \ No newline at end of file diff --git a/src/Promitor.Core.Contracts/ResourceTypes/KubernetesResourceDefinition.cs b/src/Promitor.Core.Contracts/ResourceTypes/KubernetesResourceDefinition.cs new file mode 100644 index 000000000..ab8e36cdc --- /dev/null +++ b/src/Promitor.Core.Contracts/ResourceTypes/KubernetesResourceDefinition.cs @@ -0,0 +1,13 @@ +namespace Promitor.Core.Contracts.ResourceTypes +{ + public class KubernetesResourceDefinition : AzureResourceDefinition + { + public KubernetesResourceDefinition(string subscriptionId, string resourceGroupName, string clusterName) + : base(ResourceType.Kubernetes, subscriptionId, resourceGroupName, clusterName) + { + ClusterName = clusterName; + } + + public string ClusterName { get; } + } +} \ No newline at end of file diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs index 78a420b57..a325f8db6 100644 --- a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs +++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs @@ -66,6 +66,9 @@ public IDeserializer GetDeserializerFor(ResourceType case ResourceType.KeyVault: var keyVaultLogger = _loggerFactory.CreateLogger(); return new KeyVaultDeserializer(keyVaultLogger); + case ResourceType.Kubernetes: + var kubernetesLogger = _loggerFactory.CreateLogger(); + return new KubernetesDeserializer(kubernetesLogger); case ResourceType.LogicApp: var logicAppLogger = _loggerFactory.CreateLogger(); return new LogicAppDeserializer(logicAppLogger); diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Mapping/V1MappingProfile.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Mapping/V1MappingProfile.cs index 9e45d04d2..385a7b71e 100644 --- a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Mapping/V1MappingProfile.cs +++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Mapping/V1MappingProfile.cs @@ -38,6 +38,7 @@ public V1MappingProfile() CreateMap(); CreateMap(); CreateMap(); + CreateMap(); CreateMap(); CreateMap(); CreateMap(); @@ -74,6 +75,7 @@ public V1MappingProfile() .Include() .Include() .Include() + .Include() .Include() .Include() .Include() diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/KubernetesResourceV1.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/KubernetesResourceV1.cs new file mode 100644 index 000000000..45e950e9b --- /dev/null +++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/KubernetesResourceV1.cs @@ -0,0 +1,13 @@ +namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Model.ResourceTypes +{ + /// + /// Contains the configuration required to scrape an Azure Kubernetes Service. + /// + public class KubernetesResourceV1 : AzureResourceDefinitionV1 + { + /// + /// The name of the Azure Kubernetes Service to get metrics for. + /// + public string ClusterName { get; set; } + } +} diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/KubernetesDeserializer.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/KubernetesDeserializer.cs new file mode 100644 index 000000000..a2fb4b1ee --- /dev/null +++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/KubernetesDeserializer.cs @@ -0,0 +1,14 @@ +using Microsoft.Extensions.Logging; +using Promitor.Core.Scraping.Configuration.Serialization.v1.Model.ResourceTypes; + +namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Providers +{ + public class KubernetesDeserializer : ResourceDeserializer + { + public KubernetesDeserializer(ILogger logger) : base(logger) + { + Map(resource => resource.ClusterName) + .IsRequired(); + } + } +} diff --git a/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs b/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs index bfb0fcf36..3f623cdce 100644 --- a/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs +++ b/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs @@ -62,6 +62,8 @@ public IScraper CreateScraper(ResourceType metricDefin return new IoTHubScraper(scraperConfiguration); case ResourceType.KeyVault: return new KeyVaultScraper(scraperConfiguration); + case ResourceType.Kubernetes: + return new KubernetesScraper(scraperConfiguration); case ResourceType.NetworkGateway: return new NetworkGatewayScraper(scraperConfiguration); case ResourceType.NetworkInterface: diff --git a/src/Promitor.Core.Scraping/ResourceTypes/KubernetesScraper.cs b/src/Promitor.Core.Scraping/ResourceTypes/KubernetesScraper.cs new file mode 100644 index 000000000..851ca2663 --- /dev/null +++ b/src/Promitor.Core.Scraping/ResourceTypes/KubernetesScraper.cs @@ -0,0 +1,22 @@ +using Promitor.Core.Contracts; +using Promitor.Core.Contracts.ResourceTypes; +using Promitor.Core.Scraping.Configuration.Model.Metrics; + +namespace Promitor.Core.Scraping.ResourceTypes +{ + public class KubernetesScraper : AzureMonitorScraper + { + private const string ResourceUriTemplate = "subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}"; + + public KubernetesScraper(ScraperConfiguration scraperConfiguration) : + base(scraperConfiguration) + { + } + + /// + protected override string BuildResourceUri(string subscriptionId, ScrapeDefinition scrapeDefinition, KubernetesResourceDefinition resource) + { + return string.Format(ResourceUriTemplate, subscriptionId, scrapeDefinition.ResourceGroupName, resource.ClusterName); + } + } +} \ No newline at end of file diff --git a/src/Promitor.Tests.Unit/Builders/Metrics/v1/MetricsDeclarationBuilder.cs b/src/Promitor.Tests.Unit/Builders/Metrics/v1/MetricsDeclarationBuilder.cs index 7fc9d5452..c74047405 100644 --- a/src/Promitor.Tests.Unit/Builders/Metrics/v1/MetricsDeclarationBuilder.cs +++ b/src/Promitor.Tests.Unit/Builders/Metrics/v1/MetricsDeclarationBuilder.cs @@ -608,6 +608,23 @@ public MetricsDeclarationBuilder WithKeyVaultMetric(string metricName = "promito return this; } + public MetricsDeclarationBuilder WithKubernetesMetric(string metricName = "promitor-aks", + string metricDescription = "Description for a metric", + string clusterName = "promitor-aks", + string azureMetricName = "kube_node_status_condition", + string resourceDiscoveryGroupName = "", + bool omitResource = false) + { + var resource = new KubernetesResourceV1 + { + ClusterName = clusterName + }; + + CreateAndAddMetricDefinition(ResourceType.Kubernetes, metricName, metricDescription, resourceDiscoveryGroupName, omitResource, azureMetricName, resource); + + return this; + } + private void CreateAndAddMetricDefinition(ResourceType resourceType, string metricName, string metricDescription, string resourceDiscoveryGroupName, bool omitResource, string azureMetricName, AzureResourceDefinitionV1 resource, string metricDimension = null) { CreateAndAddMetricDefinition(resourceType, metricName, metricDescription, resourceDiscoveryGroupName, omitResource, azureMetricName, new List {resource}, metricDimension); diff --git a/src/Promitor.Tests.Unit/Serialization/v1/Providers/KubernetesDeserializerTests.cs b/src/Promitor.Tests.Unit/Serialization/v1/Providers/KubernetesDeserializerTests.cs new file mode 100644 index 000000000..2a8954764 --- /dev/null +++ b/src/Promitor.Tests.Unit/Serialization/v1/Providers/KubernetesDeserializerTests.cs @@ -0,0 +1,45 @@ +using Promitor.Core.Scraping.Configuration.Serialization; +using Promitor.Core.Scraping.Configuration.Serialization.v1.Model; +using Promitor.Core.Scraping.Configuration.Serialization.v1.Model.ResourceTypes; +using Promitor.Core.Scraping.Configuration.Serialization.v1.Providers; +using System.ComponentModel; +using Xunit; + +namespace Promitor.Tests.Unit.Serialization.v1.Providers +{ + [Category("Unit")] + public class KubernetesDeserializerTests : ResourceDeserializerTest + { + private readonly KubernetesDeserializer _deserializer; + + public KubernetesDeserializerTests() + { + _deserializer = new KubernetesDeserializer(Logger); + } + + [Fact] + public void Deserialize_ClusterNameSupplied_SetsClusterName() + { + const string clusterName = "promitor-aks"; + YamlAssert.PropertySet( + _deserializer, + $"clusterName: {clusterName}", + clusterName, + r => r.ClusterName); + } + + [Fact] + public void Deserialize_ClusterNameNotSupplied_Null() + { + YamlAssert.PropertyNull( + _deserializer, + "resourceGroupName: promitor-group", + r => r.ClusterName); + } + + protected override IDeserializer CreateDeserializer() + { + return new KubernetesDeserializer(Logger); + } + } +} \ No newline at end of file diff --git a/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/KubernetesMetricsDeclarationValidationStepsTests.cs b/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/KubernetesMetricsDeclarationValidationStepsTests.cs new file mode 100644 index 000000000..ee26d4e9c --- /dev/null +++ b/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/KubernetesMetricsDeclarationValidationStepsTests.cs @@ -0,0 +1,132 @@ +using System.ComponentModel; +using Microsoft.Extensions.Logging.Abstractions; +using Promitor.Agents.Scraper.Validation.Steps; +using Promitor.Tests.Unit.Builders.Metrics.v1; +using Promitor.Tests.Unit.Stubs; +using Xunit; + +namespace Promitor.Tests.Unit.Validation.Scraper.Metrics.ResourceTypes +{ + [Category("Unit")] + public class KubernetesMetricsDeclarationValidationStepsTests : MetricsDeclarationValidationStepsTests + { + [Fact] + public void KubernetesMetricsDeclaration_DeclarationWithoutAzureMetricName_Fails() + { + // Arrange + var rawDeclaration = MetricsDeclarationBuilder.WithMetadata() + .WithKubernetesMetric(azureMetricName: string.Empty) + .Build(Mapper); + var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper); + + // Act + var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance); + var validationResult = scrapingScheduleValidationStep.Run(); + + // Assert + PromitorAssert.ValidationFailed(validationResult); + } + + [Fact] + public void KubernetesMetricsDeclaration_DeclarationWithoutMetricDescription_Succeeded() + { + // Arrange + var rawDeclaration = MetricsDeclarationBuilder.WithMetadata() + .WithKubernetesMetric(metricDescription: string.Empty) + .Build(Mapper); + var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper); + + // Act + var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance); + var validationResult = scrapingScheduleValidationStep.Run(); + + // Assert + PromitorAssert.ValidationIsSuccessful(validationResult); + } + + [Fact] + public void KubernetesMetricsDeclaration_DeclarationWithoutMetricName_Fails() + { + // Arrange + var rawDeclaration = MetricsDeclarationBuilder.WithMetadata() + .WithKubernetesMetric(string.Empty) + .Build(Mapper); + var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper); + + // Act + var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance); + var validationResult = scrapingScheduleValidationStep.Run(); + + // Assert + PromitorAssert.ValidationFailed(validationResult); + } + + [Fact] + public void KubernetesMetricsDeclaration_DeclarationWithoutClusterName_Fails() + { + // Arrange + var rawDeclaration = MetricsDeclarationBuilder.WithMetadata() + .WithKubernetesMetric(clusterName: string.Empty) + .Build(Mapper); + var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper); + + // Act + var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance); + var validationResult = scrapingScheduleValidationStep.Run(); + + // Assert + PromitorAssert.ValidationFailed(validationResult); + } + + [Fact] + public void KubernetesMetricsDeclaration_DeclarationWithoutResourceAndResourceDiscoveryGroupInfo_Fails() + { + // Arrange + var rawMetricsDeclaration = MetricsDeclarationBuilder.WithMetadata() + .WithKubernetesMetric(omitResource: true) + .Build(Mapper); + var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawMetricsDeclaration, Mapper); + + // Act + var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance); + var validationResult = scrapingScheduleValidationStep.Run(); + + // Assert + Assert.False(validationResult.IsSuccessful, "Validation was not successful"); + } + + [Fact] + public void KubernetesMetricsDeclaration_DeclarationWithoutResourceButWithResourceDiscoveryGroupInfo_Succeeds() + { + // Arrange + var rawMetricsDeclaration = MetricsDeclarationBuilder.WithMetadata() + .WithKubernetesMetric(omitResource: true, resourceDiscoveryGroupName:"sample-collection") + .Build(Mapper); + var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawMetricsDeclaration, Mapper); + + // Act + var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance); + var validationResult = scrapingScheduleValidationStep.Run(); + + // Assert + PromitorAssert.ValidationIsSuccessful(validationResult); + } + + [Fact] + public void KubernetesMetricsDeclaration_ValidDeclaration_Succeeds() + { + // Arrange + var rawMetricsDeclaration = MetricsDeclarationBuilder.WithMetadata() + .WithKubernetesMetric() + .Build(Mapper); + var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawMetricsDeclaration, Mapper); + + // Act + var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance); + var validationResult = scrapingScheduleValidationStep.Run(); + + // Assert + PromitorAssert.ValidationIsSuccessful(validationResult); + } + } +} From 963bcb78e9b458fab7f1729a82e8637500c816c9 Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Mon, 19 Oct 2020 15:54:46 +0200 Subject: [PATCH 02/10] Improve error msg when ResourceType is not matched --- src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs b/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs index 3f623cdce..9be430a7b 100644 --- a/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs +++ b/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs @@ -93,7 +93,7 @@ public IScraper CreateScraper(ResourceType metricDefin case ResourceType.WebApp: return new WebAppScraper(scraperConfiguration); default: - throw new ArgumentOutOfRangeException(); + throw new ArgumentOutOfRangeException("ResourceType", metricDefinitionResourceType, "Matching scraper not found"); } } } From 973d14bf729537c985b589c820205102dabd80ad Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Tue, 20 Oct 2020 10:49:45 +0200 Subject: [PATCH 03/10] Update docs/configuration/v2.x/metrics/kuberbetes.md Co-authored-by: Tom Kerkhove --- docs/configuration/v2.x/metrics/kuberbetes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/v2.x/metrics/kuberbetes.md b/docs/configuration/v2.x/metrics/kuberbetes.md index 33466dd65..174f13ab7 100644 --- a/docs/configuration/v2.x/metrics/kuberbetes.md +++ b/docs/configuration/v2.x/metrics/kuberbetes.md @@ -5,7 +5,7 @@ title: Azure Kubernetes Service Declaration ## Azure Kubernetes Service -![Availability Badge](https://img.shields.io/badge/Available%20Starting-v1.6-green.svg)![Resource Discovery Support Badge](https://img.shields.io/badge/Support%20for%20Resource%20Discovery-Yes-green.svg) +![Availability Badge](https://img.shields.io/badge/Available%20Starting-v2.0-green.svg)![Resource Discovery Support Badge](https://img.shields.io/badge/Support%20for%20Resource%20Discovery-Yes-green.svg) You can declare to scrape an Azure Kubernetes Service (AKS) via the `Kubernetes` resource type. From 87f02b321ff300fb0a6caf8aaa993365be42358a Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Tue, 20 Oct 2020 11:07:33 +0200 Subject: [PATCH 04/10] Rename 'Kubernetes' to 'KubernetesService' --- .../Graph/ResourceDiscoveryFactory.cs | 4 +-- ....cs => KubernetesServiceDiscoveryQuery.cs} | 4 +-- .../Factories/MetricValidatorFactory.cs | 4 +-- ...cs => KubernetesServiceMetricValidator.cs} | 6 ++-- src/Promitor.Core.Contracts/ResourceType.cs | 2 +- .../KubernetesResourceDefinition.cs | 13 -------- .../KubernetesServiceResourceDefinition.cs | 13 ++++++++ .../Core/AzureResourceDeserializerFactory.cs | 6 ++-- .../v1/Mapping/V1MappingProfile.cs | 4 +-- ...ceV1.cs => KubernetesServiceResourceV1.cs} | 2 +- ...er.cs => KubernetesServiceDeserializer.cs} | 4 +-- .../Factories/MetricScraperFactory.cs | 4 +-- ...Scraper.cs => KubernetesServiceScraper.cs} | 6 ++-- .../Metrics/v1/MetricsDeclarationBuilder.cs | 6 ++-- ... => KubernetesServiceDeserializerTests.cs} | 14 ++++----- ...MetricsDeclarationValidationStepsTests.cs} | 30 +++++++++---------- 16 files changed, 61 insertions(+), 61 deletions(-) rename src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/{KubernetesDiscoveryQuery.cs => KubernetesServiceDiscoveryQuery.cs} (72%) rename src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/{KubernetesMetricValidator.cs => KubernetesServiceMetricValidator.cs} (76%) delete mode 100644 src/Promitor.Core.Contracts/ResourceTypes/KubernetesResourceDefinition.cs create mode 100644 src/Promitor.Core.Contracts/ResourceTypes/KubernetesServiceResourceDefinition.cs rename src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/{KubernetesResourceV1.cs => KubernetesServiceResourceV1.cs} (84%) rename src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/{KubernetesDeserializer.cs => KubernetesServiceDeserializer.cs} (60%) rename src/Promitor.Core.Scraping/ResourceTypes/{KubernetesScraper.cs => KubernetesServiceScraper.cs} (74%) rename src/Promitor.Tests.Unit/Serialization/v1/Providers/{KubernetesDeserializerTests.cs => KubernetesServiceDeserializerTests.cs} (65%) rename src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/{KubernetesMetricsDeclarationValidationStepsTests.cs => KubernetesServiceMetricsDeclarationValidationStepsTests.cs} (77%) diff --git a/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceDiscoveryFactory.cs b/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceDiscoveryFactory.cs index 7dc83cf9d..6a1fa5022 100644 --- a/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceDiscoveryFactory.cs +++ b/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceDiscoveryFactory.cs @@ -34,8 +34,8 @@ public static ResourceDiscoveryQuery UseResourceDiscoveryFor(ResourceType resour return new IoTHubDiscoveryQuery(); case ResourceType.KeyVault: return new KeyVaultDiscoveryQuery(); - case ResourceType.Kubernetes: - return new KubernetesDiscoveryQuery(); + case ResourceType.KubernetesService: + return new KubernetesServiceDiscoveryQuery(); case ResourceType.LogicApp: return new LogicAppDiscoveryQuery(); case ResourceType.NetworkGateway: diff --git a/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/KubernetesDiscoveryQuery.cs b/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/KubernetesServiceDiscoveryQuery.cs similarity index 72% rename from src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/KubernetesDiscoveryQuery.cs rename to src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/KubernetesServiceDiscoveryQuery.cs index e9ea5bfe7..56d20984a 100644 --- a/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/KubernetesDiscoveryQuery.cs +++ b/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/KubernetesServiceDiscoveryQuery.cs @@ -5,7 +5,7 @@ namespace Promitor.Agents.ResourceDiscovery.Graph.ResourceTypes { - public class KubernetesDiscoveryQuery : ResourceDiscoveryQuery + public class KubernetesServiceDiscoveryQuery : ResourceDiscoveryQuery { public override string[] ResourceTypes => new[] { "Microsoft.ContainerService/managedClusters" }; public override string[] ProjectedFieldNames => new[] { "subscriptionId", "resourceGroup", "type", "name" }; @@ -14,7 +14,7 @@ public override AzureResourceDefinition ParseResults(JToken resultRowEntry) { Guard.NotNull(resultRowEntry, nameof(resultRowEntry)); - var resource = new KubernetesResourceDefinition(resultRowEntry[0]?.ToString(), resultRowEntry[1]?.ToString(), resultRowEntry[3]?.ToString()); + var resource = new KubernetesServiceResourceDefinition(resultRowEntry[0]?.ToString(), resultRowEntry[1]?.ToString(), resultRowEntry[3]?.ToString()); return resource; } } diff --git a/src/Promitor.Agents.Scraper/Validation/Factories/MetricValidatorFactory.cs b/src/Promitor.Agents.Scraper/Validation/Factories/MetricValidatorFactory.cs index b27aa69b3..3f25508c3 100644 --- a/src/Promitor.Agents.Scraper/Validation/Factories/MetricValidatorFactory.cs +++ b/src/Promitor.Agents.Scraper/Validation/Factories/MetricValidatorFactory.cs @@ -41,8 +41,8 @@ internal static IMetricValidator GetValidatorFor(ResourceType resourceType) return new IoTHubMetricValidator(); case ResourceType.KeyVault: return new KeyVaultMetricValidator(); - case ResourceType.Kubernetes: - return new KubernetesMetricValidator(); + case ResourceType.KubernetesService: + return new KubernetesServiceMetricValidator(); case ResourceType.LogicApp: return new LogicAppMetricValidator(); case ResourceType.NetworkGateway: diff --git a/src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/KubernetesMetricValidator.cs b/src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/KubernetesServiceMetricValidator.cs similarity index 76% rename from src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/KubernetesMetricValidator.cs rename to src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/KubernetesServiceMetricValidator.cs index bcbfa1ac6..da96b90e7 100644 --- a/src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/KubernetesMetricValidator.cs +++ b/src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/KubernetesServiceMetricValidator.cs @@ -7,17 +7,17 @@ namespace Promitor.Agents.Scraper.Validation.MetricDefinitions.ResourceTypes { - internal class KubernetesMetricValidator : IMetricValidator + internal class KubernetesServiceMetricValidator : IMetricValidator { public IEnumerable Validate(MetricDefinition metricDefinition) { Guard.NotNull(metricDefinition, nameof(metricDefinition)); - foreach (var resourceDefinition in metricDefinition.Resources.Cast()) + foreach (var resourceDefinition in metricDefinition.Resources.Cast()) { if (string.IsNullOrWhiteSpace(resourceDefinition.ClusterName)) { - yield return "No Azure Kubernetes Service name is configured"; + yield return "No Azure Kubernetes Service cluster name is configured"; } } } diff --git a/src/Promitor.Core.Contracts/ResourceType.cs b/src/Promitor.Core.Contracts/ResourceType.cs index 734545f6c..950400757 100644 --- a/src/Promitor.Core.Contracts/ResourceType.cs +++ b/src/Promitor.Core.Contracts/ResourceType.cs @@ -32,6 +32,6 @@ public enum ResourceType ExpressRouteCircuit = 27, ApplicationGateway = 28, NetworkGateway = 29, - Kubernetes = 30 + KubernetesService = 30 } } \ No newline at end of file diff --git a/src/Promitor.Core.Contracts/ResourceTypes/KubernetesResourceDefinition.cs b/src/Promitor.Core.Contracts/ResourceTypes/KubernetesResourceDefinition.cs deleted file mode 100644 index ab8e36cdc..000000000 --- a/src/Promitor.Core.Contracts/ResourceTypes/KubernetesResourceDefinition.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Promitor.Core.Contracts.ResourceTypes -{ - public class KubernetesResourceDefinition : AzureResourceDefinition - { - public KubernetesResourceDefinition(string subscriptionId, string resourceGroupName, string clusterName) - : base(ResourceType.Kubernetes, subscriptionId, resourceGroupName, clusterName) - { - ClusterName = clusterName; - } - - public string ClusterName { get; } - } -} \ No newline at end of file diff --git a/src/Promitor.Core.Contracts/ResourceTypes/KubernetesServiceResourceDefinition.cs b/src/Promitor.Core.Contracts/ResourceTypes/KubernetesServiceResourceDefinition.cs new file mode 100644 index 000000000..3c04b533e --- /dev/null +++ b/src/Promitor.Core.Contracts/ResourceTypes/KubernetesServiceResourceDefinition.cs @@ -0,0 +1,13 @@ +namespace Promitor.Core.Contracts.ResourceTypes +{ + public class KubernetesServiceResourceDefinition : AzureResourceDefinition + { + public KubernetesServiceResourceDefinition(string subscriptionId, string resourceGroupName, string clusterName) + : base(ResourceType.KubernetesService, subscriptionId, resourceGroupName, clusterName) + { + ClusterName = clusterName; + } + + public string ClusterName { get; } + } +} \ No newline at end of file diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs index a325f8db6..a734e1333 100644 --- a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs +++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs @@ -66,9 +66,9 @@ public IDeserializer GetDeserializerFor(ResourceType case ResourceType.KeyVault: var keyVaultLogger = _loggerFactory.CreateLogger(); return new KeyVaultDeserializer(keyVaultLogger); - case ResourceType.Kubernetes: - var kubernetesLogger = _loggerFactory.CreateLogger(); - return new KubernetesDeserializer(kubernetesLogger); + case ResourceType.KubernetesService: + var KubernetesServiceLogger = _loggerFactory.CreateLogger(); + return new KubernetesServiceDeserializer(KubernetesServiceLogger); case ResourceType.LogicApp: var logicAppLogger = _loggerFactory.CreateLogger(); return new LogicAppDeserializer(logicAppLogger); diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Mapping/V1MappingProfile.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Mapping/V1MappingProfile.cs index 385a7b71e..cfbc962b3 100644 --- a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Mapping/V1MappingProfile.cs +++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Mapping/V1MappingProfile.cs @@ -38,7 +38,7 @@ public V1MappingProfile() CreateMap(); CreateMap(); CreateMap(); - CreateMap(); + CreateMap(); CreateMap(); CreateMap(); CreateMap(); @@ -75,7 +75,7 @@ public V1MappingProfile() .Include() .Include() .Include() - .Include() + .Include() .Include() .Include() .Include() diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/KubernetesResourceV1.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/KubernetesServiceResourceV1.cs similarity index 84% rename from src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/KubernetesResourceV1.cs rename to src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/KubernetesServiceResourceV1.cs index 45e950e9b..d66019ea8 100644 --- a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/KubernetesResourceV1.cs +++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/KubernetesServiceResourceV1.cs @@ -3,7 +3,7 @@ /// /// Contains the configuration required to scrape an Azure Kubernetes Service. /// - public class KubernetesResourceV1 : AzureResourceDefinitionV1 + public class KubernetesServiceResourceV1 : AzureResourceDefinitionV1 { /// /// The name of the Azure Kubernetes Service to get metrics for. diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/KubernetesDeserializer.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/KubernetesServiceDeserializer.cs similarity index 60% rename from src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/KubernetesDeserializer.cs rename to src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/KubernetesServiceDeserializer.cs index a2fb4b1ee..dc62faf7c 100644 --- a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/KubernetesDeserializer.cs +++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/KubernetesServiceDeserializer.cs @@ -3,9 +3,9 @@ namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Providers { - public class KubernetesDeserializer : ResourceDeserializer + public class KubernetesServiceDeserializer : ResourceDeserializer { - public KubernetesDeserializer(ILogger logger) : base(logger) + public KubernetesServiceDeserializer(ILogger logger) : base(logger) { Map(resource => resource.ClusterName) .IsRequired(); diff --git a/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs b/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs index 9be430a7b..d54125ed4 100644 --- a/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs +++ b/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs @@ -62,8 +62,8 @@ public IScraper CreateScraper(ResourceType metricDefin return new IoTHubScraper(scraperConfiguration); case ResourceType.KeyVault: return new KeyVaultScraper(scraperConfiguration); - case ResourceType.Kubernetes: - return new KubernetesScraper(scraperConfiguration); + case ResourceType.KubernetesService: + return new KubernetesServiceScraper(scraperConfiguration); case ResourceType.NetworkGateway: return new NetworkGatewayScraper(scraperConfiguration); case ResourceType.NetworkInterface: diff --git a/src/Promitor.Core.Scraping/ResourceTypes/KubernetesScraper.cs b/src/Promitor.Core.Scraping/ResourceTypes/KubernetesServiceScraper.cs similarity index 74% rename from src/Promitor.Core.Scraping/ResourceTypes/KubernetesScraper.cs rename to src/Promitor.Core.Scraping/ResourceTypes/KubernetesServiceScraper.cs index 851ca2663..fc98e629c 100644 --- a/src/Promitor.Core.Scraping/ResourceTypes/KubernetesScraper.cs +++ b/src/Promitor.Core.Scraping/ResourceTypes/KubernetesServiceScraper.cs @@ -4,17 +4,17 @@ namespace Promitor.Core.Scraping.ResourceTypes { - public class KubernetesScraper : AzureMonitorScraper + public class KubernetesServiceScraper : AzureMonitorScraper { private const string ResourceUriTemplate = "subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}"; - public KubernetesScraper(ScraperConfiguration scraperConfiguration) : + public KubernetesServiceScraper(ScraperConfiguration scraperConfiguration) : base(scraperConfiguration) { } /// - protected override string BuildResourceUri(string subscriptionId, ScrapeDefinition scrapeDefinition, KubernetesResourceDefinition resource) + protected override string BuildResourceUri(string subscriptionId, ScrapeDefinition scrapeDefinition, KubernetesServiceResourceDefinition resource) { return string.Format(ResourceUriTemplate, subscriptionId, scrapeDefinition.ResourceGroupName, resource.ClusterName); } diff --git a/src/Promitor.Tests.Unit/Builders/Metrics/v1/MetricsDeclarationBuilder.cs b/src/Promitor.Tests.Unit/Builders/Metrics/v1/MetricsDeclarationBuilder.cs index c74047405..5b9bea311 100644 --- a/src/Promitor.Tests.Unit/Builders/Metrics/v1/MetricsDeclarationBuilder.cs +++ b/src/Promitor.Tests.Unit/Builders/Metrics/v1/MetricsDeclarationBuilder.cs @@ -608,19 +608,19 @@ public MetricsDeclarationBuilder WithKeyVaultMetric(string metricName = "promito return this; } - public MetricsDeclarationBuilder WithKubernetesMetric(string metricName = "promitor-aks", + public MetricsDeclarationBuilder WithKubernetesServiceMetric(string metricName = "promitor-aks", string metricDescription = "Description for a metric", string clusterName = "promitor-aks", string azureMetricName = "kube_node_status_condition", string resourceDiscoveryGroupName = "", bool omitResource = false) { - var resource = new KubernetesResourceV1 + var resource = new KubernetesServiceResourceV1 { ClusterName = clusterName }; - CreateAndAddMetricDefinition(ResourceType.Kubernetes, metricName, metricDescription, resourceDiscoveryGroupName, omitResource, azureMetricName, resource); + CreateAndAddMetricDefinition(ResourceType.KubernetesService, metricName, metricDescription, resourceDiscoveryGroupName, omitResource, azureMetricName, resource); return this; } diff --git a/src/Promitor.Tests.Unit/Serialization/v1/Providers/KubernetesDeserializerTests.cs b/src/Promitor.Tests.Unit/Serialization/v1/Providers/KubernetesServiceDeserializerTests.cs similarity index 65% rename from src/Promitor.Tests.Unit/Serialization/v1/Providers/KubernetesDeserializerTests.cs rename to src/Promitor.Tests.Unit/Serialization/v1/Providers/KubernetesServiceDeserializerTests.cs index 2a8954764..8f9f25038 100644 --- a/src/Promitor.Tests.Unit/Serialization/v1/Providers/KubernetesDeserializerTests.cs +++ b/src/Promitor.Tests.Unit/Serialization/v1/Providers/KubernetesServiceDeserializerTests.cs @@ -8,20 +8,20 @@ namespace Promitor.Tests.Unit.Serialization.v1.Providers { [Category("Unit")] - public class KubernetesDeserializerTests : ResourceDeserializerTest + public class KubernetesServiceDeserializerTests : ResourceDeserializerTest { - private readonly KubernetesDeserializer _deserializer; + private readonly KubernetesServiceDeserializer _deserializer; - public KubernetesDeserializerTests() + public KubernetesServiceDeserializerTests() { - _deserializer = new KubernetesDeserializer(Logger); + _deserializer = new KubernetesServiceDeserializer(Logger); } [Fact] public void Deserialize_ClusterNameSupplied_SetsClusterName() { const string clusterName = "promitor-aks"; - YamlAssert.PropertySet( + YamlAssert.PropertySet( _deserializer, $"clusterName: {clusterName}", clusterName, @@ -31,7 +31,7 @@ public void Deserialize_ClusterNameSupplied_SetsClusterName() [Fact] public void Deserialize_ClusterNameNotSupplied_Null() { - YamlAssert.PropertyNull( + YamlAssert.PropertyNull( _deserializer, "resourceGroupName: promitor-group", r => r.ClusterName); @@ -39,7 +39,7 @@ public void Deserialize_ClusterNameNotSupplied_Null() protected override IDeserializer CreateDeserializer() { - return new KubernetesDeserializer(Logger); + return new KubernetesServiceDeserializer(Logger); } } } \ No newline at end of file diff --git a/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/KubernetesMetricsDeclarationValidationStepsTests.cs b/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/KubernetesServiceMetricsDeclarationValidationStepsTests.cs similarity index 77% rename from src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/KubernetesMetricsDeclarationValidationStepsTests.cs rename to src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/KubernetesServiceMetricsDeclarationValidationStepsTests.cs index ee26d4e9c..d593057d9 100644 --- a/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/KubernetesMetricsDeclarationValidationStepsTests.cs +++ b/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/KubernetesServiceMetricsDeclarationValidationStepsTests.cs @@ -8,14 +8,14 @@ namespace Promitor.Tests.Unit.Validation.Scraper.Metrics.ResourceTypes { [Category("Unit")] - public class KubernetesMetricsDeclarationValidationStepsTests : MetricsDeclarationValidationStepsTests + public class KubernetesServiceMetricsDeclarationValidationStepsTests : MetricsDeclarationValidationStepsTests { [Fact] - public void KubernetesMetricsDeclaration_DeclarationWithoutAzureMetricName_Fails() + public void KubernetesServiceMetricsDeclaration_DeclarationWithoutAzureMetricName_Fails() { // Arrange var rawDeclaration = MetricsDeclarationBuilder.WithMetadata() - .WithKubernetesMetric(azureMetricName: string.Empty) + .WithKubernetesServiceMetric(azureMetricName: string.Empty) .Build(Mapper); var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper); @@ -28,11 +28,11 @@ public void KubernetesMetricsDeclaration_DeclarationWithoutAzureMetricName_Fails } [Fact] - public void KubernetesMetricsDeclaration_DeclarationWithoutMetricDescription_Succeeded() + public void KubernetesServiceMetricsDeclaration_DeclarationWithoutMetricDescription_Succeeded() { // Arrange var rawDeclaration = MetricsDeclarationBuilder.WithMetadata() - .WithKubernetesMetric(metricDescription: string.Empty) + .WithKubernetesServiceMetric(metricDescription: string.Empty) .Build(Mapper); var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper); @@ -45,11 +45,11 @@ public void KubernetesMetricsDeclaration_DeclarationWithoutMetricDescription_Suc } [Fact] - public void KubernetesMetricsDeclaration_DeclarationWithoutMetricName_Fails() + public void KubernetesServiceMetricsDeclaration_DeclarationWithoutMetricName_Fails() { // Arrange var rawDeclaration = MetricsDeclarationBuilder.WithMetadata() - .WithKubernetesMetric(string.Empty) + .WithKubernetesServiceMetric(string.Empty) .Build(Mapper); var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper); @@ -62,11 +62,11 @@ public void KubernetesMetricsDeclaration_DeclarationWithoutMetricName_Fails() } [Fact] - public void KubernetesMetricsDeclaration_DeclarationWithoutClusterName_Fails() + public void KubernetesServiceMetricsDeclaration_DeclarationWithoutClusterName_Fails() { // Arrange var rawDeclaration = MetricsDeclarationBuilder.WithMetadata() - .WithKubernetesMetric(clusterName: string.Empty) + .WithKubernetesServiceMetric(clusterName: string.Empty) .Build(Mapper); var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper); @@ -79,11 +79,11 @@ public void KubernetesMetricsDeclaration_DeclarationWithoutClusterName_Fails() } [Fact] - public void KubernetesMetricsDeclaration_DeclarationWithoutResourceAndResourceDiscoveryGroupInfo_Fails() + public void KubernetesServiceMetricsDeclaration_DeclarationWithoutResourceAndResourceDiscoveryGroupInfo_Fails() { // Arrange var rawMetricsDeclaration = MetricsDeclarationBuilder.WithMetadata() - .WithKubernetesMetric(omitResource: true) + .WithKubernetesServiceMetric(omitResource: true) .Build(Mapper); var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawMetricsDeclaration, Mapper); @@ -96,11 +96,11 @@ public void KubernetesMetricsDeclaration_DeclarationWithoutResourceAndResourceDi } [Fact] - public void KubernetesMetricsDeclaration_DeclarationWithoutResourceButWithResourceDiscoveryGroupInfo_Succeeds() + public void KubernetesServiceMetricsDeclaration_DeclarationWithoutResourceButWithResourceDiscoveryGroupInfo_Succeeds() { // Arrange var rawMetricsDeclaration = MetricsDeclarationBuilder.WithMetadata() - .WithKubernetesMetric(omitResource: true, resourceDiscoveryGroupName:"sample-collection") + .WithKubernetesServiceMetric(omitResource: true, resourceDiscoveryGroupName:"sample-collection") .Build(Mapper); var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawMetricsDeclaration, Mapper); @@ -113,11 +113,11 @@ public void KubernetesMetricsDeclaration_DeclarationWithoutResourceButWithResour } [Fact] - public void KubernetesMetricsDeclaration_ValidDeclaration_Succeeds() + public void KubernetesServiceMetricsDeclaration_ValidDeclaration_Succeeds() { // Arrange var rawMetricsDeclaration = MetricsDeclarationBuilder.WithMetadata() - .WithKubernetesMetric() + .WithKubernetesServiceMetric() .Build(Mapper); var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawMetricsDeclaration, Mapper); From ef1106f23e2bf63dcd84daf2ddb570f58e6f8740 Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Tue, 20 Oct 2020 11:13:38 +0200 Subject: [PATCH 05/10] Change 'Kuberntes' to 'KubernetesService' in docs --- docs/configuration/v2.x/metrics/kuberbetes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/configuration/v2.x/metrics/kuberbetes.md b/docs/configuration/v2.x/metrics/kuberbetes.md index 174f13ab7..38e82c933 100644 --- a/docs/configuration/v2.x/metrics/kuberbetes.md +++ b/docs/configuration/v2.x/metrics/kuberbetes.md @@ -8,7 +8,7 @@ title: Azure Kubernetes Service Declaration ![Availability Badge](https://img.shields.io/badge/Available%20Starting-v2.0-green.svg)![Resource Discovery Support Badge](https://img.shields.io/badge/Support%20for%20Resource%20Discovery-Yes-green.svg) You can declare to scrape an Azure Kubernetes Service (AKS) -via the `Kubernetes` resource type. +via the `KubernetesService` resource type. The following fields need to be provided: @@ -21,7 +21,7 @@ Example: ```yaml name: azure_kubernetes_available_cpu_cores description: "Available CPU cores in cluster" -resourceType: Kubernetes +resourceType: KubernetesService azureMetricConfiguration: metricName: kube_node_status_allocatable_cpu_cores aggregation: From 4d45384a92ee3569b97734e6f47fd17015bf3aa9 Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Tue, 20 Oct 2020 11:19:37 +0200 Subject: [PATCH 06/10] Add link to Kubernetes Service metrics in page --- docs/configuration/v2.x/resource-discovery.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/configuration/v2.x/resource-discovery.md b/docs/configuration/v2.x/resource-discovery.md index 3680bb2ff..3f981061b 100644 --- a/docs/configuration/v2.x/resource-discovery.md +++ b/docs/configuration/v2.x/resource-discovery.md @@ -101,6 +101,7 @@ Dynamic resource discovery is supported for the following scrapers: - [Azure IoT Hub](metrics/iot-hub) - [Azure IoT Hub Device Provisioning Service (DPS)](metrics/iot-hub-device-provisioning-service) - [Azure Key Vault](metrics/key-vault) +- [Azure Kubernetes Service](metrics/kubernetes) - [Azure Logic Apps](metrics/logic-apps) - [Azure Network Gateway](metrics/network-gateway) - [Azure Network Interface](metrics/network-interface) From 45e55e9cd21b4a7674f151c065906ea6c653bd3b Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Tue, 20 Oct 2020 11:24:47 +0200 Subject: [PATCH 07/10] Add Kubernetes Service to changelog --- changelog/content/experimental/unreleased.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog/content/experimental/unreleased.md b/changelog/content/experimental/unreleased.md index 927a807b3..3da923a6e 100644 --- a/changelog/content/experimental/unreleased.md +++ b/changelog/content/experimental/unreleased.md @@ -15,6 +15,7 @@ version: - {{% tag added %}} Support for scraping Azure Express Route circuits ([docs](https://promitor.io/configuration/v2.x/metrics/express-route-circuit) | [#1251](https://github.com/tomkerkhove/promitor/issues/1251) | Contributed by [@bluepixbe](https://github.com/bluepixbe) 🎉). - {{% tag added %}} Support for scraping Azure Application Gateway ([docs](https://promitor.io/configuration/v2.x/metrics/application-gateway) | [#1251](https://github.com/tomkerkhove/promitor/issues/313) | Contributed by [@bluepixbe](https://github.com/bluepixbe) 🎉). - {{% tag added %}} Support for scraping Azure Network Gateway ([docs](https://promitor.io/configuration/v2.x/metrics/network-gateway) | [#1264](https://github.com/tomkerkhove/promitor/issues/1264) | Contributed by [@bluepixbe](https://github.com/bluepixbe) 🎉). +- {{% tag added %}} Support for scraping Azure Kubernetes Service ([docs](https://promitor.io/configuration/v2.x/metrics/kubernetes) | [#333](https://github.com/tomkerkhove/promitor/issues/333) | Contributed by [@jkataja](https://github.com/jkataja) 🎉). - {{% tag added %}} New validation rule to ensure at least one resource or resource collection is configured to scrape - {{% tag added %}} Provide suggestions when unknown fields are found in the metrics config. ([#1105](https://github.com/tomkerkhove/promitor/issues/1105) | Contributed by [@adamconnelly](https://github.com/adamconnelly) 🎉). - {{% tag added %}} Add validation to ensure the scraping schedule is a valid Cron expression. ([#1103](https://github.com/tomkerkhove/promitor/issues/1103) | Contributed by [@adamconnelly](https://github.com/adamconnelly) 🎉). From e4415966a73f9564cc459a1070f2580e6c064113 Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Tue, 20 Oct 2020 11:33:40 +0200 Subject: [PATCH 08/10] Fix typo in file name --- docs/configuration/v2.x/metrics/{kuberbetes.md => kubernetes.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/configuration/v2.x/metrics/{kuberbetes.md => kubernetes.md} (100%) diff --git a/docs/configuration/v2.x/metrics/kuberbetes.md b/docs/configuration/v2.x/metrics/kubernetes.md similarity index 100% rename from docs/configuration/v2.x/metrics/kuberbetes.md rename to docs/configuration/v2.x/metrics/kubernetes.md From 984a137d41c7c3f86a8c442d101eda5fd8572742 Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Tue, 20 Oct 2020 14:21:31 +0200 Subject: [PATCH 09/10] Fix warning for argument type string in exception --- src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs b/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs index d54125ed4..d62c83763 100644 --- a/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs +++ b/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs @@ -93,7 +93,7 @@ public IScraper CreateScraper(ResourceType metricDefin case ResourceType.WebApp: return new WebAppScraper(scraperConfiguration); default: - throw new ArgumentOutOfRangeException("ResourceType", metricDefinitionResourceType, "Matching scraper not found"); + throw new ArgumentOutOfRangeException("metricDefinitionResourceType", metricDefinitionResourceType, "Matching scraper not found"); } } } From 56858fc6883a930ff665e23174f782bc3c5d4646 Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Tue, 20 Oct 2020 14:30:47 +0200 Subject: [PATCH 10/10] Fix varable naming for code quality check --- .../Serialization/v1/Core/AzureResourceDeserializerFactory.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs index a734e1333..3123bda1f 100644 --- a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs +++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs @@ -67,8 +67,8 @@ public IDeserializer GetDeserializerFor(ResourceType var keyVaultLogger = _loggerFactory.CreateLogger(); return new KeyVaultDeserializer(keyVaultLogger); case ResourceType.KubernetesService: - var KubernetesServiceLogger = _loggerFactory.CreateLogger(); - return new KubernetesServiceDeserializer(KubernetesServiceLogger); + var kubernetesServiceLogger = _loggerFactory.CreateLogger(); + return new KubernetesServiceDeserializer(kubernetesServiceLogger); case ResourceType.LogicApp: var logicAppLogger = _loggerFactory.CreateLogger(); return new LogicAppDeserializer(logicAppLogger);