diff --git a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/api/Azure.Provisioning.CloudMachine.net8.0.cs b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/api/Azure.Provisioning.CloudMachine.net8.0.cs index a526056e2055..3e3c5e0fb611 100644 --- a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/api/Azure.Provisioning.CloudMachine.net8.0.cs +++ b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/api/Azure.Provisioning.CloudMachine.net8.0.cs @@ -4,6 +4,7 @@ public static partial class Azd { public static void Init(Azure.CloudMachine.CloudMachineClient client, string? infraDirectory = null) { } public static void Init(Azure.CloudMachine.CloudMachineInfrastructure infra, string? infraDirectory = null) { } + public static void InitDeployment(Azure.CloudMachine.CloudMachineInfrastructure infra, string? webProjectName) { } } public static partial class CloudMachineClientExtensions { diff --git a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/api/Azure.Provisioning.CloudMachine.netstandard2.0.cs b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/api/Azure.Provisioning.CloudMachine.netstandard2.0.cs index a526056e2055..3e3c5e0fb611 100644 --- a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/api/Azure.Provisioning.CloudMachine.netstandard2.0.cs +++ b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/api/Azure.Provisioning.CloudMachine.netstandard2.0.cs @@ -4,6 +4,7 @@ public static partial class Azd { public static void Init(Azure.CloudMachine.CloudMachineClient client, string? infraDirectory = null) { } public static void Init(Azure.CloudMachine.CloudMachineInfrastructure infra, string? infraDirectory = null) { } + public static void InitDeployment(Azure.CloudMachine.CloudMachineInfrastructure infra, string? webProjectName) { } } public static partial class CloudMachineClientExtensions { diff --git a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/src/CloudMachineInfrastructure/CloudMachineInfrastructure.cs b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/src/CloudMachineInfrastructure/CloudMachineInfrastructure.cs index 2e3c0adb9138..e61889cdc478 100644 --- a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/src/CloudMachineInfrastructure/CloudMachineInfrastructure.cs +++ b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/src/CloudMachineInfrastructure/CloudMachineInfrastructure.cs @@ -62,7 +62,7 @@ public CloudMachineInfrastructure(string? cmId = default) AddFeature(new ServiceBusSubscriptionFeature("cm_servicebus_subscription_private", sbTopicPrivate)); // TODO: should private connections not be in the Connections collection? AddFeature(new ServiceBusSubscriptionFeature("cm_servicebus_subscription_default", sbTopicDefault)); var systemTopic = AddFeature(new EventGridSystemTopicFeature(Id, storage, "Microsoft.Storage.StorageAccounts")); - AddFeature(new SystemTopicEventSubscriptionFeature("cm_eventgrid_subscription_blob", systemTopic, sbTopicPrivate, sbNamespace)); + AddFeature(new SystemTopicEventSubscriptionFeature("cm-eventgrid-subscription-blob", systemTopic, sbTopicPrivate, sbNamespace)); } public T AddFeature(T feature) where T: CloudMachineFeature diff --git a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/src/Tooling/Azd.cs b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/src/Tooling/Azd.cs index 9f5fcc7a1727..31c49bd3c195 100644 --- a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/src/Tooling/Azd.cs +++ b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/src/Tooling/Azd.cs @@ -6,6 +6,7 @@ using Azure.Provisioning.Primitives; using Azure.Provisioning.Resources; using Azure.Provisioning.Expressions; +using System.Linq; namespace Azure.CloudMachine; @@ -27,7 +28,8 @@ public static void Init(CloudMachineClient client, string? infraDirectory = defa public static void Init(CloudMachineInfrastructure infra, string? infraDirectory = default) { - if (infraDirectory == default) infraDirectory = Path.Combine(".", "infra"); + if (infraDirectory == default) + infraDirectory = Path.Combine(".", "infra"); Directory.CreateDirectory(infraDirectory); @@ -64,6 +66,28 @@ public static void Init(CloudMachineInfrastructure infra, string? infraDirectory WriteMainParametersFile(infraDirectory); } + + public static void InitDeployment(CloudMachineInfrastructure infra, string? webProjectName) + { + var webCsproj = webProjectName switch + { + null => ".", + _ => webProjectName.EndsWith(".csproj") ? webProjectName : $"{webProjectName}.csproj" + }; + var webProjDirectory = webCsproj switch + { + "." => null, + _ => Directory + .GetFiles(Directory.GetCurrentDirectory(), "*" + webCsproj, SearchOption.AllDirectories) + .SingleOrDefault() + }; + if (webProjDirectory != null) + { + webProjDirectory = Path.GetDirectoryName(webProjDirectory)?.Replace(Directory.GetCurrentDirectory(), "."); + } + WriteAzureYamlFile(webProjDirectory ?? "./", infra.Id); + } + private static void WriteMainParametersFile(string infraDirectory) { File.WriteAllText(Path.Combine(infraDirectory, $"{MainBicepName}.parameters.json"), @@ -85,4 +109,23 @@ private static void WriteMainParametersFile(string infraDirectory) } """); } + + private static void WriteAzureYamlFile(string webProjDirectory, string cmId, string? hostType = "appservice") + { + if (webProjDirectory == ".") + { + webProjDirectory = "./"; + } + + File.WriteAllText(Path.Combine(Directory.GetCurrentDirectory(), "azure.yaml"), + $""" +name: {cmId} +resourceGroup: {cmId} +services: + {cmId}: + project: {webProjDirectory} # path to your web project + language: csharp # one of the supported languages + host: {hostType} # one of the supported Azure services +"""); + } } diff --git a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/src/Tooling/CloudMachineCommands.cs b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/src/Tooling/CloudMachineCommands.cs index 4685dda5683e..5d84fc3d91eb 100644 --- a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/src/Tooling/CloudMachineCommands.cs +++ b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/src/Tooling/CloudMachineCommands.cs @@ -33,6 +33,19 @@ public static bool Execute(string[] args, Action? co return Handled(exitProcessIfHandled); } + if (args[0] == "-init") + { + Azd.Init(cmi); + + string? projName = default; + if (args.Length > 1) + { + projName = args[1]; + } + Azd.InitDeployment(cmi, projName); + return Handled(exitProcessIfHandled); + } + if (args[0] == "-tsp") { GenerateTsp(cmi.Endpoints); diff --git a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/CommandsTests.cs b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/CommandsTests.cs index 0afa31a6a375..abf2c219752e 100644 --- a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/CommandsTests.cs +++ b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/CommandsTests.cs @@ -13,4 +13,10 @@ public void ListModels() { CloudMachineCommands.Execute(["-ai", "chat"], exitProcessIfHandled: false); } + + [Test] + public void DoInit() + { + CloudMachineCommands.Execute(["-init", "demo.csproj"], exitProcessIfHandled: false); + } } diff --git a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/Data/GenerateBicep.bicep b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/Data/GenerateBicep.bicep index eebc294e692e..ced4dd22bad1 100644 --- a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/Data/GenerateBicep.bicep +++ b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/Data/GenerateBicep.bicep @@ -193,7 +193,7 @@ resource cm_eventgrid_topic 'Microsoft.EventGrid/systemTopics@2022-06-15' = { } resource cm_eventgrid_subscription_blob 'Microsoft.EventGrid/systemTopics/eventSubscriptions@2022-06-15' = { - name: 'cm_eventgrid_subscription_blob' + name: 'cm-eventgrid-subscription-blob' properties: { deliveryWithResourceIdentity: { identity: { diff --git a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/Data/JustCloudMachine.bicep b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/Data/JustCloudMachine.bicep index 4657dd5b9f34..53f8f3e3e637 100644 --- a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/Data/JustCloudMachine.bicep +++ b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/Data/JustCloudMachine.bicep @@ -193,7 +193,7 @@ resource cm_eventgrid_topic 'Microsoft.EventGrid/systemTopics@2022-06-15' = { } resource cm_eventgrid_subscription_blob 'Microsoft.EventGrid/systemTopics/eventSubscriptions@2022-06-15' = { - name: 'cm_eventgrid_subscription_blob' + name: 'cm-eventgrid-subscription-blob' properties: { deliveryWithResourceIdentity: { identity: { diff --git a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/Data/OpenAI.bicep b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/Data/OpenAI.bicep index ef7b1529ef13..9b0926880e81 100644 --- a/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/Data/OpenAI.bicep +++ b/sdk/cloudmachine/Azure.Provisioning.CloudMachine/tests/Data/OpenAI.bicep @@ -193,7 +193,7 @@ resource cm_eventgrid_topic 'Microsoft.EventGrid/systemTopics@2022-06-15' = { } resource cm_eventgrid_subscription_blob 'Microsoft.EventGrid/systemTopics/eventSubscriptions@2022-06-15' = { - name: 'cm_eventgrid_subscription_blob' + name: 'cm-eventgrid-subscription-blob' properties: { deliveryWithResourceIdentity: { identity: { diff --git a/sdk/cloudmachine/README.MD b/sdk/cloudmachine/README.md similarity index 82% rename from sdk/cloudmachine/README.MD rename to sdk/cloudmachine/README.md index cb6c50be5a2a..d3c3d9be0ba7 100644 --- a/sdk/cloudmachine/README.MD +++ b/sdk/cloudmachine/README.md @@ -1,9 +1,19 @@ -# Azure CloudMachine +# Azure CloudMachine client library for .NETyy Write Azure apps in 5 minutes ## Getting started +### Install the package + +Install the client library for .NET with [NuGet](https://www.nuget.org/ ): + +```dotnetcli +dotnet add package Azure.CloudMachine.All --prerelease +``` + +### Authenticate the Client + ### Prerequisites * You must have an [Azure subscription](https://azure.microsoft.com/free/dotnet/). @@ -13,6 +23,10 @@ Write Azure apps in 5 minutes * You must have npm installed * You must be logged into Azure CLI and Azure Developer CLI +## Key concepts + +Write Azure apps in 5 minutes using simplified opinionated APIs and declarative resource provisioning. + ### Walkthrough #### Create Server Project @@ -38,7 +52,7 @@ using Azure.CloudMachine; if (CloudMachineInfrastructure.Configure(args)) return; ``` -The `CloudMachineInfrastructure.Configure` call allows running the app with a `-bicep` switch, which will generate bicep files required to provision CloudMachine resources in Azure. Let's generate these bicep files now. +The `CloudMachineInfrastructure.Configure` call allows running the app with a `-bicep` switch, which will generate bicep files required to provision CloudMachine resources in Azure. Let's generate these bicep files now. ```dotnetcli dotnet run -bicep ``` @@ -56,7 +70,7 @@ When provisioning finishes, you should see something like the following in the c ```dotnetcli (✓) Done: Resource group: cm125957681369428 (627ms) ``` -And if you go to your Azure portal, or execute the following az command, you can see the resource group created. The resource group will contain resources such as Storage, ServiceBus, and EventGrid. +And if you go to your Azure portal, or execute the following az command, you can see the resource group created. The resource group will contain resources such as Storage, ServiceBus, and EventGrid. ```dotnetcli az resource list --resource-group --output table ``` @@ -92,7 +106,7 @@ class AssistantService { var client = cm.GetOpenAIChatClient(); ChatCompletion completion = await client.CompleteChatAsync(message); return completion.Content[0].Text; - } + } } ``` Lastly, create an instance of the service and call the `Chat` method when the user navigates to the root URL: @@ -123,7 +137,7 @@ class AssistantService { var client = cm.GetOpenAIChatClient(); ChatCompletion completion = await client.CompleteChatAsync(message); return completion.Content[0].Text; - } + } internal static void Configure(CloudMachineInfrastructure cm) { cm.AddFeature(new OpenAIFeature() { @@ -181,7 +195,7 @@ class AssistantService : IAssistantService { var client = cm.GetOpenAIChatClient(); ChatCompletion completion = await client.CompleteChatAsync(message); return completion.Content[0].Text; - } + } internal static void Configure(CloudMachineInfrastructure cm) { cm.AddFeature(new OpenAIFeature() { @@ -270,3 +284,37 @@ Go back to the client project command window and start the client: dotnet run ``` You can use the simple command line app to ask Azure OpenAI some questions. + +## Examples + +## Troubleshooting + +- File an issue via [GitHub Issues](https://github.com/Azure/azure-sdk-for-net/issues). +- Check [previous questions](https://stackoverflow.com/questions/tagged/azure+.net) or ask new ones on Stack Overflow using Azure and .NET tags. + +## Next steps + +## Contributing + +For details on contributing to this repository, see the [contributing +guide][cg]. + +This project welcomes contributions and suggestions. Most contributions +require you to agree to a Contributor License Agreement (CLA) declaring +that you have the right to, and actually do, grant us the rights to use +your contribution. For details, visit . + +When you submit a pull request, a CLA-bot will automatically determine +whether you need to provide a CLA and decorate the PR appropriately +(for example, label, comment). Follow the instructions provided by the +bot. You'll only need to do this action once across all repositories +using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct][coc]. For +more information, see the [Code of Conduct FAQ][coc_faq] or contact + with any other questions or comments. + + +[cg]: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/resourcemanager/Azure.ResourceManager/docs/CONTRIBUTING.md +[coc]: https://opensource.microsoft.com/codeofconduct/ +[coc_faq]: https://opensource.microsoft.com/codeofconduct/faq/ \ No newline at end of file