Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide support for resource discovery in all Azure Clouds #1184

Merged
merged 3 commits into from
Jul 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System.Collections.Generic;
using Promitor.Core.Serialization.Enum;

namespace Promitor.Agents.ResourceDiscovery.Configuration
{
public class AzureLandscape
{
public string TenantId { get; set; }
public List<string> Subscriptions { get; set; }
public AzureCloud Cloud { get; set; } = AzureCloud.Global;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Promitor.Agents.ResourceDiscovery.Configuration;
using Promitor.Agents.ResourceDiscovery.Graph.Exceptions;
using Promitor.Agents.ResourceDiscovery.Graph.Model;
using Promitor.Core.Extensions;

namespace Promitor.Agents.ResourceDiscovery.Graph
{
Expand Down Expand Up @@ -210,7 +211,8 @@ private async Task<ResourceGraphClient> GetOrCreateClient()

private async Task<ResourceGraphClient> CreateClientAsync()
{
var credentials = await Authentication.GetServiceClientCredentialsAsync("https://management.core.windows.net", QueryApplicationId, _queryApplicationSecret, TenantId);
var azureEnvironment = _resourceDeclarationMonitor.CurrentValue.AzureLandscape.Cloud.GetAzureEnvironment();
var credentials = await Authentication.GetServiceClientCredentialsAsync(azureEnvironment.ManagementEndpoint, QueryApplicationId, _queryApplicationSecret, TenantId);
return new ResourceGraphClient(credentials);
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/Promitor.Agents.Scraper/Docs/Open-Api.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Extensions.Logging;
using Promitor.Core.Extensions;
using Promitor.Core.Scraping.Configuration.Serialization.v1.Model;
using Promitor.Core.Serialization.Enum;
using YamlDotNet.RepresentationModel;

namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Core
Expand All @@ -23,18 +26,16 @@ public AzureMetadataDeserializer(ILogger<AzureMetadataDeserializer> logger) : ba

private object DetermineAzureCloud(string rawAzureCloud, KeyValuePair<YamlNode, YamlNode> nodePair, IErrorReporter errorReporter)
{
if (System.Enum.TryParse<AzureCloudsV1>(rawAzureCloud, out var azureCloud))
if (Enum.TryParse<AzureCloud>(rawAzureCloud, out var azureCloud))
{
switch (azureCloud)
try
{
case AzureCloudsV1.Global:
return AzureEnvironment.AzureGlobalCloud;
case AzureCloudsV1.China:
return AzureEnvironment.AzureChinaCloud;
case AzureCloudsV1.Germany:
return AzureEnvironment.AzureGermanCloud;
case AzureCloudsV1.UsGov:
return AzureEnvironment.AzureUSGovernment;
var azureEnvironment = azureCloud.GetAzureEnvironment();
return azureEnvironment;
}
catch (ArgumentOutOfRangeException)
{
errorReporter.ReportError(nodePair.Value, $"'{rawAzureCloud}' is not a supported value for 'cloud'.");
}
}
else
Expand Down

This file was deleted.

31 changes: 31 additions & 0 deletions src/Promitor.Core/Extensions/AzureCloudExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Promitor.Core.Serialization.Enum;

namespace Promitor.Core.Extensions
{
public static class AzureCloudExtensions
{
/// <summary>
/// Get Azure environment information
/// </summary>
/// <param name="azureCloud">Microsoft Azure cloud</param>
/// <returns>Azure environment information for specified cloud</returns>
public static AzureEnvironment GetAzureEnvironment(this AzureCloud azureCloud)
{
switch (azureCloud)
{
case AzureCloud.Global:
return AzureEnvironment.AzureGlobalCloud;
case AzureCloud.China:
return AzureEnvironment.AzureChinaCloud;
case AzureCloud.Germany:
return AzureEnvironment.AzureGermanCloud;
case AzureCloud.UsGov:
return AzureEnvironment.AzureUSGovernment;
default:
throw new ArgumentOutOfRangeException(nameof(azureCloud), "No Azure environment is known for");
}
}
}
}
11 changes: 11 additions & 0 deletions src/Promitor.Core/Serialization/Enum/AzureCloud.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Promitor.Core.Serialization.Enum
{
public enum AzureCloud
{
Unspecified,
Global,
China,
UsGov,
Germany
}
}
79 changes: 79 additions & 0 deletions src/Promitor.Tests.Unit/Azure/AzureCloudUnitTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System;
using System.ComponentModel;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Promitor.Core.Extensions;
using Promitor.Core.Serialization.Enum;
using Xunit;

namespace Promitor.Tests.Unit.Azure
{
[Category("Unit")]
public class AzureCloudUnitTests
{
[Fact]
public void GetAzureEnvironment_ForAzureGlobalCloud_ProvidesCorrectEnvironmentInfo()
{
// Arrange
var azureCloud = AzureCloud.Global;
var expectedEnvironment = AzureEnvironment.AzureGlobalCloud;

// Act
var azureEnvironment = azureCloud.GetAzureEnvironment();

// Assert
PromitorAssert.ContainsSameAzureEnvironmentInfo(expectedEnvironment, azureEnvironment);
}

[Fact]
public void GetAzureEnvironment_ForAzureChinaCloud_ProvidesCorrectEnvironmentInfo()
{
// Arrange
var azureCloud = AzureCloud.China;
var expectedEnvironment = AzureEnvironment.AzureChinaCloud;

// Act
var azureEnvironment = azureCloud.GetAzureEnvironment();

// Assert
PromitorAssert.ContainsSameAzureEnvironmentInfo(expectedEnvironment, azureEnvironment);
}

[Fact]
public void GetAzureEnvironment_ForAzureGermanCloud_ProvidesCorrectEnvironmentInfo()
{
// Arrange
var azureCloud = AzureCloud.Germany;
var expectedEnvironment = AzureEnvironment.AzureGermanCloud;

// Act
var azureEnvironment = azureCloud.GetAzureEnvironment();

// Assert
PromitorAssert.ContainsSameAzureEnvironmentInfo(expectedEnvironment, azureEnvironment);
}

[Fact]
public void GetAzureEnvironment_ForAzureUSGovernmentCloud_ProvidesCorrectEnvironmentInfo()
{
// Arrange
var azureCloud = AzureCloud.UsGov;
var expectedEnvironment = AzureEnvironment.AzureUSGovernment;

// Act
var azureEnvironment = azureCloud.GetAzureEnvironment();

// Assert
PromitorAssert.ContainsSameAzureEnvironmentInfo(expectedEnvironment, azureEnvironment);
}

[Fact]
public void GetAzureEnvironment_ForUnspecifiedAzureCloud_ThrowsException()
{
// Arrange
var azureCloud = AzureCloud.Unspecified;

// Act & Assert
Assert.Throws<ArgumentOutOfRangeException>(()=> azureCloud.GetAzureEnvironment());
}
}
}
23 changes: 23 additions & 0 deletions src/Promitor.Tests.Unit/PromitorAssert.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Xunit;

namespace Promitor.Tests.Unit
{
internal class PromitorAssert : Assert
{
/// <summary>
/// Verifies if Azure environment information are equal
/// </summary>
public static void ContainsSameAzureEnvironmentInfo(AzureEnvironment expectedEnvironment, AzureEnvironment azureEnvironment)
{
NotNull(azureEnvironment);
Equal(expectedEnvironment.Name, azureEnvironment.Name);
Equal(expectedEnvironment.AuthenticationEndpoint, azureEnvironment.AuthenticationEndpoint);
Equal(expectedEnvironment.GraphEndpoint, azureEnvironment.GraphEndpoint);
Equal(expectedEnvironment.KeyVaultSuffix, azureEnvironment.KeyVaultSuffix);
Equal(expectedEnvironment.ManagementEndpoint, azureEnvironment.ManagementEndpoint);
Equal(expectedEnvironment.ResourceManagerEndpoint, azureEnvironment.ResourceManagerEndpoint);
Equal(expectedEnvironment.StorageEndpointSuffix, azureEnvironment.StorageEndpointSuffix);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Extensions.Logging.Abstractions;
using Promitor.Core.Scraping.Configuration.Serialization.v1.Core;
using Promitor.Core.Scraping.Configuration.Serialization.v1.Model;
using Promitor.Core.Serialization.Enum;
using Xunit;
using YamlDotNet.RepresentationModel;

Expand All @@ -20,13 +20,29 @@ public AzureMetadataDeserializerTests()
}

[Fact]
public void Deserialize_AzureCloudSupplied_SetsAzureCloud()
public void Deserialize_AzureCloudSuppliedWithUnspecified_SetsAzureChinaCloud()
{
var yamlNode = YamlUtils.CreateYamlNode(
$@"azureMetadata:
cloud: '{AzureCloud.Unspecified}'");
var azureMetadataNode = (YamlMappingNode)yamlNode.Children["azureMetadata"];
var errorNode = azureMetadataNode.Children["cloud"];

YamlAssert.ReportsError(
_deserializer,
azureMetadataNode,
errorNode,
"'Unspecified' is not a supported value for 'cloud'.");
}

[Fact]
public void Deserialize_AzureCloudSupplied_SetsAzureChinaCloud()
{
AzureEnvironment azureCloud = AzureEnvironment.AzureChinaCloud;

var yamlText =
$@"azureMetadata:
cloud: '{AzureCloudsV1.China}'";
cloud: '{AzureCloud.China}'";

YamlAssert.PropertySet(
_deserializer,
Expand Down Expand Up @@ -57,7 +73,7 @@ public void Deserialize_AzureCloudNotSupplied_SetsGlobalAzureCloud()
public void Deserialize_InvalidAzureCloudSupplied_ReportsError()
{
var yamlNode = YamlUtils.CreateYamlNode(
@"azureMetadata:
@"azureMetadata:
cloud: invalid");
var azureMetadataNode = (YamlMappingNode)yamlNode.Children["azureMetadata"];
var errorNode = azureMetadataNode.Children["cloud"];
Expand Down