forked from Azure/azure-sdk-for-net
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* added solution, and a placeholder test file * added basic azd integration * made principalId an azd parameter * removed dependency on concrete config system * removed accidentaly added file * refactored * started experimenting with storage APIs * changed resource names to be == to CMID * small PR feedback * fixed build break * merged * removed unfinished work * added cache and messaging * use cache * PR feedback * cached SB Client * updated api file
- Loading branch information
1 parent
2899e0b
commit fe6df81
Showing
11 changed files
with
531 additions
and
31 deletions.
There are no files selected for viewing
37 changes: 37 additions & 0 deletions
37
sdk/provisioning/Azure.Provisioning.CloudMachine/Azure.CloudMachine.sln
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 17 | ||
VisualStudioVersion = 17.12.35309.182 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Provisioning.CloudMachine", "src\Azure.Provisioning.CloudMachine.csproj", "{AF572EE6-69D4-4C6D-87C0-763281AB7AED}" | ||
EndProject | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Provisioning.CloudMachine.Tests", "tests\Azure.Provisioning.CloudMachine.Tests.csproj", "{46DCEF27-4157-4FB6-A283-B8484EC45665}" | ||
EndProject | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Core.TestFramework", "..\..\core\Azure.Core.TestFramework\src\Azure.Core.TestFramework.csproj", "{67BF7830-BE03-4F13-B062-5D747A553542}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{AF572EE6-69D4-4C6D-87C0-763281AB7AED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{AF572EE6-69D4-4C6D-87C0-763281AB7AED}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{AF572EE6-69D4-4C6D-87C0-763281AB7AED}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{AF572EE6-69D4-4C6D-87C0-763281AB7AED}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{46DCEF27-4157-4FB6-A283-B8484EC45665}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{46DCEF27-4157-4FB6-A283-B8484EC45665}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{46DCEF27-4157-4FB6-A283-B8484EC45665}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{46DCEF27-4157-4FB6-A283-B8484EC45665}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{67BF7830-BE03-4F13-B062-5D747A553542}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{67BF7830-BE03-4F13-B062-5D747A553542}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{67BF7830-BE03-4F13-B062-5D747A553542}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{67BF7830-BE03-4F13-B062-5D747A553542}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {66A0BAC4-5774-4C62-941C-D9E8F9D2A3E9} | ||
EndGlobalSection | ||
EndGlobal |
49 changes: 46 additions & 3 deletions
49
...ing/Azure.Provisioning.CloudMachine/api/Azure.Provisioning.CloudMachine.netstandard2.0.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,54 @@ | ||
namespace Azure.CloudMachine | ||
{ | ||
public partial class ClientCache | ||
{ | ||
public ClientCache() { } | ||
public T Get<T>(string id, System.Func<T> value) where T : class { throw null; } | ||
} | ||
public partial class CloudMachineClient | ||
{ | ||
protected CloudMachineClient() { } | ||
public CloudMachineClient(Azure.Identity.DefaultAzureCredential? credential = null, Microsoft.Extensions.Configuration.IConfiguration? configuration = null) { } | ||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] | ||
public Azure.CloudMachine.ClientCache ClientCache { get { throw null; } } | ||
public Azure.Core.TokenCredential Credential { get { throw null; } } | ||
public string Id { get { throw null; } } | ||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] | ||
public Azure.CloudMachine.CloudMachineClient.CloudMachineProperties Properties { get { throw null; } } | ||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] | ||
public override bool Equals(object? obj) { throw null; } | ||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] | ||
public override int GetHashCode() { throw null; } | ||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] | ||
public override string ToString() { throw null; } | ||
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] | ||
public partial struct CloudMachineProperties | ||
{ | ||
private object _dummy; | ||
private int _dummyPrimitive; | ||
public System.Uri BlobServiceUri { get { throw null; } } | ||
public System.Uri DefaultContainerUri { get { throw null; } } | ||
public System.Uri KeyVaultUri { get { throw null; } } | ||
public string ServiceBusNamespace { get { throw null; } } | ||
} | ||
} | ||
public static partial class MessagingServices | ||
{ | ||
public static void Send(this Azure.CloudMachine.CloudMachineClient cm, object serializable) { } | ||
} | ||
public static partial class StorageServices | ||
{ | ||
public static System.BinaryData Download(this Azure.CloudMachine.CloudMachineClient cm, string name) { throw null; } | ||
public static string Upload(this Azure.CloudMachine.CloudMachineClient cm, object json, string? name = null) { throw null; } | ||
} | ||
} | ||
namespace Azure.Provisioning.CloudMachine | ||
{ | ||
public partial class CloudMachineInfrastructure : Azure.Provisioning.Infrastructure | ||
{ | ||
public CloudMachineInfrastructure(string name = "cm") : base (default(string)) { } | ||
public CloudMachineInfrastructure(string cloudMachineId) : base (default(string)) { } | ||
public Azure.Provisioning.BicepParameter PrincipalIdParameter { get { throw null; } } | ||
public Azure.Provisioning.BicepParameter PrincipalNameParameter { get { throw null; } } | ||
public Azure.Provisioning.BicepParameter PrincipalTypeParameter { get { throw null; } } | ||
public override Azure.Provisioning.ProvisioningPlan Build(Azure.Provisioning.ProvisioningContext? context = null) { throw null; } | ||
public static bool Configure(string[] args, System.Action<Azure.Provisioning.CloudMachine.CloudMachineInfrastructure>? configure = null) { throw null; } | ||
} | ||
} |
142 changes: 142 additions & 0 deletions
142
sdk/provisioning/Azure.Provisioning.CloudMachine/src/Azd.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System.IO; | ||
using Azure.Provisioning; | ||
using Azure.Provisioning.CloudMachine; | ||
using Azure.Provisioning.Primitives; | ||
using Azure.Provisioning.Resources; | ||
using Azure.Provisioning.Expressions; | ||
using System.Text.Json.Nodes; | ||
using System.Text.Json; | ||
using System; | ||
|
||
namespace Azure.CloudMachine; | ||
|
||
internal static class Azd | ||
{ | ||
private const string MainBicepName = "main"; | ||
private const string ResourceGroupVersion = "2024-03-01"; | ||
|
||
internal static void Init(string infraDirectory, CloudMachineInfrastructure cmi) | ||
{ | ||
Directory.CreateDirectory(infraDirectory); | ||
|
||
cmi.Build().Save(infraDirectory); | ||
var cmid = ReadOrCreateCmid(); | ||
|
||
// main.bicep | ||
var location = new BicepParameter("location", typeof(string)); | ||
var principalId = new BicepParameter("principalId", typeof(string)); | ||
|
||
ResourceGroup rg = new(nameof(rg), ResourceGroupVersion) | ||
{ | ||
Name = cmid, | ||
Location = location | ||
}; | ||
|
||
Infrastructure mainBicep = new("main") | ||
{ | ||
TargetScope = "subscription" | ||
}; | ||
ModuleImport import = new("cm", $"cm.bicep") | ||
{ | ||
Name = "cm", | ||
Scope = new IdentifierExpression(rg.ResourceName) | ||
}; | ||
import.Parameters.Add(nameof(location), location); | ||
import.Parameters.Add(nameof(principalId), principalId); | ||
|
||
mainBicep.Add(rg); | ||
mainBicep.Add(import); | ||
mainBicep.Add(location); | ||
mainBicep.Add(principalId); | ||
mainBicep.Build().Save(infraDirectory); | ||
|
||
WriteMainParametersFile(infraDirectory); | ||
} | ||
|
||
private static void WriteMainParametersFile(string infraDirectory) | ||
{ | ||
File.WriteAllText(Path.Combine(infraDirectory, $"{MainBicepName}.parameters.json"), | ||
""" | ||
{ | ||
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", | ||
"contentVersion": "1.0.0.0", | ||
"parameters": { | ||
"environmentName": { | ||
"value": "${AZURE_ENV_NAME}" | ||
}, | ||
"location" : { | ||
"value" : "${AZURE_LOCATION}" | ||
}, | ||
"principalId": { | ||
"value": "${AZURE_PRINCIPAL_ID}" | ||
} | ||
} | ||
} | ||
"""); | ||
} | ||
|
||
internal static string ReadOrCreateCmid() | ||
{ | ||
string appsettings = Path.Combine(".", "appsettings.json"); | ||
|
||
string? cmid; | ||
if (!File.Exists(appsettings)) | ||
{ | ||
cmid = GenerateCloudMachineId(); | ||
|
||
using FileStream file = File.OpenWrite(appsettings); | ||
Utf8JsonWriter writer = new Utf8JsonWriter(file); | ||
writer.WriteStartObject(); | ||
writer.WritePropertyName("CloudMachine"u8); | ||
writer.WriteStartObject(); | ||
writer.WriteString("ID"u8, cmid); | ||
writer.WriteEndObject(); | ||
writer.WriteEndObject(); | ||
writer.Flush(); | ||
return cmid; | ||
} | ||
|
||
using FileStream json = File.OpenRead(appsettings); | ||
using JsonDocument jd = JsonDocument.Parse(json); | ||
JsonElement je = jd.RootElement; | ||
// attempt to read CM configuration from existing configuration file | ||
if (je.TryGetProperty("CloudMachine"u8, out JsonElement cm)) | ||
{ | ||
if (!cm.TryGetProperty("ID"u8, out JsonElement id)) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
cmid = id.GetString(); | ||
if (cmid == null) | ||
throw new NotImplementedException(); | ||
return cmid; | ||
} | ||
else | ||
{ // add CM configuration to existing file | ||
JsonNode? root = JsonValue.Parse(appsettings); | ||
if (root is null) | ||
throw new NotImplementedException(); | ||
|
||
if (root is not JsonObject obj) | ||
throw new NotImplementedException(); | ||
|
||
var cmProperties = new JsonObject(); | ||
cmid = GenerateCloudMachineId(); | ||
cmProperties.Add("ID", cmid); | ||
obj.Add("CloudMachine", cmProperties); | ||
} | ||
|
||
return cmid; | ||
|
||
static string GenerateCloudMachineId() | ||
{ | ||
var guid = Guid.NewGuid(); | ||
var guidString = guid.ToString("N"); | ||
var cnId = "cm" + guidString.Substring(0, 15); // we can increase it to 20, but the template name cannot be that long | ||
return cnId; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
sdk/provisioning/Azure.Provisioning.CloudMachine/src/Client/ClientCache.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace Azure.CloudMachine; | ||
|
||
// TODO: this is a very demo implementation. We need to do better | ||
public class ClientCache | ||
{ | ||
private readonly Dictionary<string, object> _clients = new Dictionary<string, object>(); | ||
|
||
// TODO: consider uisng ICLientCreator instead of Func | ||
public T Get<T>(string id, Func<T> value) where T: class | ||
{ | ||
lock (_clients) | ||
{ | ||
if (_clients.TryGetValue(id, out object cached)) | ||
{ | ||
T client = (T)cached; | ||
return client; | ||
} | ||
|
||
if (_clients.Count > 100) | ||
{ | ||
GC(); | ||
} | ||
T created = value(); | ||
_clients.Add(id, created); | ||
return created; | ||
} | ||
|
||
void GC() | ||
{ | ||
foreach (object value in _clients.Values) | ||
{ | ||
if (value is IDisposable disposable) disposable.Dispose(); | ||
} | ||
_clients.Clear(); | ||
} | ||
} | ||
} |
74 changes: 74 additions & 0 deletions
74
sdk/provisioning/Azure.Provisioning.CloudMachine/src/Client/CloudMachine.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.ComponentModel; | ||
using Azure.Core; | ||
using Azure.Identity; | ||
using Microsoft.Extensions.Configuration; | ||
|
||
namespace Azure.CloudMachine; | ||
|
||
public partial class CloudMachineClient | ||
{ | ||
public string Id { get; } | ||
|
||
public TokenCredential Credential { get; } = new ChainedTokenCredential( | ||
new AzureDeveloperCliCredential() | ||
); | ||
|
||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "AZC0007:DO provide a minimal constructor that takes only the parameters required to connect to the service.", Justification = "<Pending>")] | ||
public CloudMachineClient(DefaultAzureCredential? credential = default, IConfiguration? configuration = default) | ||
{ | ||
if (credential != default) | ||
{ | ||
Credential = credential; | ||
} | ||
|
||
string? cmid; | ||
if (configuration == default) | ||
{ | ||
cmid = Azd.ReadOrCreateCmid(); | ||
} | ||
else | ||
{ | ||
cmid = configuration["CloudMachine:ID"]; | ||
if (cmid == null) | ||
throw new Exception("CloudMachine:ID configuration value missing"); | ||
} | ||
|
||
Id = cmid!; | ||
} | ||
|
||
protected CloudMachineClient() | ||
{ | ||
Id = "CM"; | ||
} | ||
|
||
[EditorBrowsable(EditorBrowsableState.Never)] | ||
public ClientCache ClientCache { get; } = new ClientCache(); | ||
|
||
[EditorBrowsable(EditorBrowsableState.Never)] | ||
public CloudMachineProperties Properties => new CloudMachineProperties(this); | ||
|
||
public struct CloudMachineProperties | ||
{ | ||
private readonly CloudMachineClient _cm; | ||
|
||
internal CloudMachineProperties(CloudMachineClient cm) => _cm = cm; | ||
public Uri DefaultContainerUri => new Uri($"https://{_cm.Id}.blob.core.windows.net/default"); | ||
public Uri BlobServiceUri => new Uri($"https://{_cm.Id}.blob.core.windows.net/"); | ||
public Uri KeyVaultUri => new Uri($"https://{_cm.Id}.vault.azure.net/"); | ||
|
||
public string ServiceBusNamespace => $"{_cm.Id}.servicebus.windows.net"; | ||
} | ||
|
||
[EditorBrowsable(EditorBrowsableState.Never)] | ||
public override bool Equals(object? obj) => base.Equals(obj); | ||
[EditorBrowsable(EditorBrowsableState.Never)] | ||
public override int GetHashCode() => base.GetHashCode(); | ||
|
||
[EditorBrowsable(EditorBrowsableState.Never)] | ||
public override string ToString() => Id; | ||
} |
Oops, something went wrong.