从代码 (c#) 部署 Azure 函数
Deploy Azure function from code (c#)
如何使用代码作为字符串(在 c# 中)将 azure 函数(按计划执行)部署到给定的 azure 函数应用程序?
我将使用 ARM 模板部署 azure fund 应用程序(+它需要的一切)https://github.com/Azure/azure-quickstart-templates/tree/master/101-function-app-create-dynamic,可以通过代码部署;
但我没有看到通过代码将函数部署到函数应用程序的方法。
+ 多一点上下文:部署将从应用程序服务发生,因此最好不要有任何 NuGet 以外的依赖项。例如。我不喜欢从 c# 调用 azure cli 的想法。
如果您要直接从代码部署函数本身而不是使用 CI/CD 管道,那么最好的办法是使用 Kudu REST APIs 将函数代码作为 zip 文件上传到 运行 函数应用程序。您应该能够使用 HttpClient 或任何其他 .NET REST 库来凑合。
正如 Jesse Carter 提到的,我们可以使用 Kudu Zip Api 来做到这一点。我为此做了一个演示。它在我这边正常工作。以下是我的详细步骤:
准备:
注册AD应用并为应用分配角色,详情请参考Azure official tutorials。之后我们可以从Azure Portal获取tenantId, appId, secretKey。
1.Prepare一个认证文件,我们可以从githubdocument.
获取更多信息
subscription=########-####-####-####-############
client=########-####-####-####-############
tenant=########-####-####-####-############
managementURI=https\://management.core.windows.net/
baseURL=https\://management.azure.com/
authURL=https\://login.windows.net/
graphURL=https\://graph.windows.net/
2.Zip需要发布的文件
步骤:
1.Create 一个 C# 控制台项目
2.ReferenceMicrosoft.Azure.Management.ResourceManager.Fluent and Microsoft.Azure.Management.AppService.Fluent,更多详细信息请参考packages.config文件部分。
3.Add Program.cs 文件中的以下代码
var credentials = SdkContext.AzureCredentialsFactory.FromFile(@"authentication file path");
var azure = Azure
.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(credentials)
.WithDefaultSubscription();
var webFunctionAppName = "azure function name";
var webFunctionApp = azure.AppServices.FunctionApps.List().Where(x => x.Name.Equals(webFunctionAppName))?.First();
var ftpUsername = azure.AppServices.FunctionApps.GetById(webFunctionApp.Id).GetPublishingProfile().FtpUsername;
var username = ftpUsername.Split('\').ToList()[1];
var password = azure.AppServices.FunctionApps.GetById(webFunctionApp.Id).GetPublishingProfile().FtpPassword;
var base64Auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{username}:{password}"));
var file = File.ReadAllBytes(@"zip file path");
MemoryStream stream = new MemoryStream(file);
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Basic " + base64Auth);
var baseUrl = new Uri($"https://{webFunctionAppName}.scm.azurewebsites.net/");
var requestURl = baseUrl+ "api/zip/site/wwwroot";
var httpContent = new StreamContent(stream);
var response = client.PutAsync(requestURl, httpContent).Result;
}
4.Test 来自本地
5.Check Azure kudu 工具发布的结果(https://yourazurefunctionanme.scm.azurewebsites.net/)
packages.config
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Azure.Management.AppService.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Batch.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Cdn.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Compute.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.ContainerRegistry.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Dns.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.DocumentDB.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Graph.RBAC.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.KeyVault.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Network.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Redis.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.ResourceManager.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.ServiceBus.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Sql.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Storage.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.TrafficManager.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="2.28.3" targetFramework="net452" />
<package id="Microsoft.Rest.ClientRuntime" version="2.3.8" targetFramework="net452" />
<package id="Microsoft.Rest.ClientRuntime.Azure" version="3.3.8" targetFramework="net452" />
<package id="Microsoft.Rest.ClientRuntime.Azure.Authentication" version="2.3.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
</packages>
如何使用代码作为字符串(在 c# 中)将 azure 函数(按计划执行)部署到给定的 azure 函数应用程序?
我将使用 ARM 模板部署 azure fund 应用程序(+它需要的一切)https://github.com/Azure/azure-quickstart-templates/tree/master/101-function-app-create-dynamic,可以通过代码部署;
但我没有看到通过代码将函数部署到函数应用程序的方法。
+ 多一点上下文:部署将从应用程序服务发生,因此最好不要有任何 NuGet 以外的依赖项。例如。我不喜欢从 c# 调用 azure cli 的想法。
如果您要直接从代码部署函数本身而不是使用 CI/CD 管道,那么最好的办法是使用 Kudu REST APIs 将函数代码作为 zip 文件上传到 运行 函数应用程序。您应该能够使用 HttpClient 或任何其他 .NET REST 库来凑合。
正如 Jesse Carter 提到的,我们可以使用 Kudu Zip Api 来做到这一点。我为此做了一个演示。它在我这边正常工作。以下是我的详细步骤:
准备:
注册AD应用并为应用分配角色,详情请参考Azure official tutorials。之后我们可以从Azure Portal获取tenantId, appId, secretKey。
1.Prepare一个认证文件,我们可以从githubdocument.
获取更多信息subscription=########-####-####-####-############
client=########-####-####-####-############
tenant=########-####-####-####-############
managementURI=https\://management.core.windows.net/
baseURL=https\://management.azure.com/
authURL=https\://login.windows.net/
graphURL=https\://graph.windows.net/
2.Zip需要发布的文件
步骤:
1.Create 一个 C# 控制台项目
2.ReferenceMicrosoft.Azure.Management.ResourceManager.Fluent and Microsoft.Azure.Management.AppService.Fluent,更多详细信息请参考packages.config文件部分。
3.Add Program.cs 文件中的以下代码
var credentials = SdkContext.AzureCredentialsFactory.FromFile(@"authentication file path");
var azure = Azure
.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(credentials)
.WithDefaultSubscription();
var webFunctionAppName = "azure function name";
var webFunctionApp = azure.AppServices.FunctionApps.List().Where(x => x.Name.Equals(webFunctionAppName))?.First();
var ftpUsername = azure.AppServices.FunctionApps.GetById(webFunctionApp.Id).GetPublishingProfile().FtpUsername;
var username = ftpUsername.Split('\').ToList()[1];
var password = azure.AppServices.FunctionApps.GetById(webFunctionApp.Id).GetPublishingProfile().FtpPassword;
var base64Auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{username}:{password}"));
var file = File.ReadAllBytes(@"zip file path");
MemoryStream stream = new MemoryStream(file);
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Basic " + base64Auth);
var baseUrl = new Uri($"https://{webFunctionAppName}.scm.azurewebsites.net/");
var requestURl = baseUrl+ "api/zip/site/wwwroot";
var httpContent = new StreamContent(stream);
var response = client.PutAsync(requestURl, httpContent).Result;
}
4.Test 来自本地
5.Check Azure kudu 工具发布的结果(https://yourazurefunctionanme.scm.azurewebsites.net/)
packages.config
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Azure.Management.AppService.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Batch.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Cdn.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Compute.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.ContainerRegistry.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Dns.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.DocumentDB.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Graph.RBAC.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.KeyVault.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Network.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Redis.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.ResourceManager.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.ServiceBus.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Sql.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.Storage.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.Azure.Management.TrafficManager.Fluent" version="1.1.3" targetFramework="net452" />
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="2.28.3" targetFramework="net452" />
<package id="Microsoft.Rest.ClientRuntime" version="2.3.8" targetFramework="net452" />
<package id="Microsoft.Rest.ClientRuntime.Azure" version="3.3.8" targetFramework="net452" />
<package id="Microsoft.Rest.ClientRuntime.Azure.Authentication" version="2.3.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
</packages>