如何以编程方式 Enable/Disable Azure Function
How to Enable/Disable Azure Function programmatically
有没有办法以编程方式 enable/disable Azure 函数?
我可以 enable/disable 使用 "Manage" 部分下门户的功能,这会导致将请求发送到 https://<myfunctionapp>.scm.azurewebsites.net/api/functions/<myfunction>
JSON 有效负载看起来有点像:
{
"name":"SystemEventFunction",
"config":{
"disabled":true,
"bindings":[
// the bindings for this function
]
}
// lots of other properties (mostly URIs)
}
我正在门户之外创建一个管理工具,允许用户启用和禁用功能。
希望我可以避免手动创建 JSON 负载,所以我想知道 SDK(WebJobs??)中是否有具有此功能的东西。
不,这目前是不可能的。 function.json 中的 disabled
元数据 属性 决定功能是否启用。当您 enable/disable 在门户中时,门户只会更新该值。
不确定它是否能满足您的需求,但我会指出还有一个 host.json functions
数组可用于控制将要加载的函数集(记录 here)。因此,例如,如果您只想启用 10 个函数中的 2 个,则可以将此 属性 设置为仅包含这 2 个函数名称的数组(例如 "functions": [ "QueueProcessor", "GitHubWebHook" ]
),并且只有那些 [=21] =].但是,这与 enable/disable 略有不同,因为您将无法通过门户调用排除的函数,而您可以通过门户调用 disabled 函数。
我想您可以使用 Kudu REST API(特别是 VFS)来更新 function.json 中的 disabled 元数据 属性。那会禁用该功能吗?
这是 Kudu REST API。 https://github.com/projectkudu/kudu/wiki/REST-API
根据@James Z. 的回答,我在 C# 中创建了以下 class,允许您以编程方式禁用/启用 Azure 函数。
functionsSiteRoot 构造函数参数是 Functions 应用程序的 Kudu 根,例如 https://your-functions-web-app.scm.azurewebsites.net/api/vfs/site/wwwroot/
用户名和密码可以在您的功能的应用服务设置中"Get publish profile"获得。
public class FunctionsHelper : IFunctionsHelper
{
private readonly string _username;
private readonly string _password;
private readonly string _functionsSiteRoot;
private WebClient _webClient;
public FunctionsHelper(string username, string password, string functionsSiteRoot)
{
_username = username;
_password = password;
_functionsSiteRoot = functionsSiteRoot;
_webClient = new WebClient
{
Headers = { ["ContentType"] = "application/json" },
Credentials = new NetworkCredential(username, password),
BaseAddress = functionsSiteRoot
};
}
public void StopFunction(string functionName)
{
SetFunctionState(functionName, isDisabled: true);
}
public void StartFunction(string functionName)
{
SetFunctionState(functionName, isDisabled: false);
}
private void SetFunctionState(string functionName, bool isDisabled)
{
var functionJson =
JsonConvert.DeserializeObject<FunctionSettings>(_webClient.DownloadString(GetFunctionJsonUrl(functionName)));
functionJson.disabled = isDisabled;
_webClient.Headers["If-Match"] = "*";
_webClient.UploadString(GetFunctionJsonUrl(functionName), "PUT", JsonConvert.SerializeObject(functionJson));
}
private static string GetFunctionJsonUrl(string functionName)
{
return $"{functionName}/function.json";
}
}
internal class FunctionSettings
{
public bool disabled { get; set; }
public List<Binding> bindings { get; set; }
}
internal class Binding
{
public string name { get; set; }
public string type { get; set; }
public string direction { get; set; }
public string queueName { get; set; }
public string connection { get; set; }
public string accessRights { get; set; }
}
除了上面@DavidGouge 的回答,他 post 编写的代码确实有效,我刚刚对其进行了测试,并将在我的应用程序中使用它。但是它需要一些调整:
移除对 IFunctionsHelper 的继承。我不确定那个界面是什么,但它不是必需的。
如下更改绑定的 class 定义:
internal class Binding
{
public string name { get; set; }
public string type { get; set; }
public string direction { get; set; }
public string queueName { get; set; }
public string connection { get; set; }
public string accessRights { get; set; }
public string schedule { get; set; }
}
之后就可以了。
P.S。我会把它作为对原始答案的评论,但我在 Stack Overflow 上的声誉不足以 post 评论!
用于通过 CLI 禁用 Azure 功能的 CLI 命令 - 已记录 here
az functionapp config appsettings set --name <myFunctionApp> \
--resource-group <myResourceGroup> \
--settings AzureWebJobs.QueueTrigger.Disabled=true
我在 运行 执行上述命令时捕获了 fiddler。
Azure CLI 在 Python 进程上运行 python 进程正在向
发出请求
https://management.azure.com 更新应用程序设置。
在以下 REST 端点中获得了对同一端点的引用:
https://docs.microsoft.com/en-us/rest/api/appservice/webapps/updateapplicationsettings
请求 URI :
Headers :
Authorization: Bearer <> ;
Content-Type: application/json; charset=utf-8
请求Body:
{"kind": "<class 'str'>", "properties":JSON}
我们可以对属性进行硬编码或动态获取。要禁用该功能,必须更新属性的 JSON 节点:Azure.WebJobs.QueueTrigger.Disabled = True
要获取可以使用端点的属性,您可以参考 Web Apps - List Application Settings
输出如下所示:
希望这对您有所帮助:)
结合使用@Satya V 和@DavidGouge 的解决方案,我想出了这个:
public class FunctionsHelper
{
private readonly ClientSecretCredential _tokenCredential;
private readonly HttpClient _httpClient;
public FunctionsHelper(string tenantId, string clientId, string clientSecret, string subscriptionId, string resourceGroup, string functionAppName)
{
var baseUrl =
$"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Web/sites/{functionAppName}/";
var httpClient = new HttpClient
{
BaseAddress = new Uri(baseUrl)
};
_httpClient = httpClient;
_tokenCredential = new ClientSecretCredential(tenantId, clientId, clientSecret);
}
private async Task SetAuthHeader()
{
var accessToken = await GetAccessToken();
_httpClient.DefaultRequestHeaders.Authorization = AuthenticationHeaderValue.Parse($"Bearer {accessToken}");
}
private async Task<string> GetAccessToken()
{
return (await _tokenCredential.GetTokenAsync(
new TokenRequestContext(new[] {"https://management.azure.com/.default"}))).Token;
}
public async Task StopFunction(string functionName)
{
await SetFunctionState(functionName, isDisabled: true);
}
public async Task StartFunction(string functionName)
{
await SetFunctionState(functionName, isDisabled: false);
}
private async Task SetFunctionState(string functionName, bool isDisabled)
{
await SetAuthHeader();
var appSettings = await GetAppSettings();
appSettings.properties[$"AzureWebJobs.{functionName}.Disabled"] = isDisabled ? "1" : "0";
var payloadJson = JsonConvert.SerializeObject(new
{
kind = "<class 'str'>", appSettings.properties
});
var stringContent = new StringContent(payloadJson, Encoding.UTF8, "application/json");
await _httpClient.PutAsync("config/appsettings?api-version=2019-08-01", stringContent);
}
private async Task<AppSettings> GetAppSettings()
{
var res = await _httpClient.PostAsync("config/appsettings/list?api-version=2019-08-01", null);
var content = await res.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<AppSettings>(content);
}
}
internal class AppSettings
{
public Dictionary<string, string> properties { get; set; }
}
使用 Kudu api 更新 function.json 文件的问题是它会在任何后续部署中被覆盖。这使用 Azure 的 Rest Api 来更新应用程序的配置。不过,您首先需要 Azure 服务原则才能使用 api。
使用 Azure Cli,您可以 运行 az ad sp create-for-rbac
生成服务原则并获取客户端 ID 和客户端密码。因为 UpdateConfiguration 端点不允许您更新单个值,并且会用新值覆盖整个 Configuration 对象,所以您必须首先获取所有当前 Configuration 值,更新您想要的值,然后使用新值调用 Update 端点配置键和值。
这看起来是最简单的本地开发解决方案。
有没有办法以编程方式 enable/disable Azure 函数?
我可以 enable/disable 使用 "Manage" 部分下门户的功能,这会导致将请求发送到 https://<myfunctionapp>.scm.azurewebsites.net/api/functions/<myfunction>
JSON 有效负载看起来有点像:
{
"name":"SystemEventFunction",
"config":{
"disabled":true,
"bindings":[
// the bindings for this function
]
}
// lots of other properties (mostly URIs)
}
我正在门户之外创建一个管理工具,允许用户启用和禁用功能。
希望我可以避免手动创建 JSON 负载,所以我想知道 SDK(WebJobs??)中是否有具有此功能的东西。
不,这目前是不可能的。 function.json 中的 disabled
元数据 属性 决定功能是否启用。当您 enable/disable 在门户中时,门户只会更新该值。
不确定它是否能满足您的需求,但我会指出还有一个 host.json functions
数组可用于控制将要加载的函数集(记录 here)。因此,例如,如果您只想启用 10 个函数中的 2 个,则可以将此 属性 设置为仅包含这 2 个函数名称的数组(例如 "functions": [ "QueueProcessor", "GitHubWebHook" ]
),并且只有那些 [=21] =].但是,这与 enable/disable 略有不同,因为您将无法通过门户调用排除的函数,而您可以通过门户调用 disabled 函数。
我想您可以使用 Kudu REST API(特别是 VFS)来更新 function.json 中的 disabled 元数据 属性。那会禁用该功能吗? 这是 Kudu REST API。 https://github.com/projectkudu/kudu/wiki/REST-API
根据@James Z. 的回答,我在 C# 中创建了以下 class,允许您以编程方式禁用/启用 Azure 函数。
functionsSiteRoot 构造函数参数是 Functions 应用程序的 Kudu 根,例如 https://your-functions-web-app.scm.azurewebsites.net/api/vfs/site/wwwroot/
用户名和密码可以在您的功能的应用服务设置中"Get publish profile"获得。
public class FunctionsHelper : IFunctionsHelper
{
private readonly string _username;
private readonly string _password;
private readonly string _functionsSiteRoot;
private WebClient _webClient;
public FunctionsHelper(string username, string password, string functionsSiteRoot)
{
_username = username;
_password = password;
_functionsSiteRoot = functionsSiteRoot;
_webClient = new WebClient
{
Headers = { ["ContentType"] = "application/json" },
Credentials = new NetworkCredential(username, password),
BaseAddress = functionsSiteRoot
};
}
public void StopFunction(string functionName)
{
SetFunctionState(functionName, isDisabled: true);
}
public void StartFunction(string functionName)
{
SetFunctionState(functionName, isDisabled: false);
}
private void SetFunctionState(string functionName, bool isDisabled)
{
var functionJson =
JsonConvert.DeserializeObject<FunctionSettings>(_webClient.DownloadString(GetFunctionJsonUrl(functionName)));
functionJson.disabled = isDisabled;
_webClient.Headers["If-Match"] = "*";
_webClient.UploadString(GetFunctionJsonUrl(functionName), "PUT", JsonConvert.SerializeObject(functionJson));
}
private static string GetFunctionJsonUrl(string functionName)
{
return $"{functionName}/function.json";
}
}
internal class FunctionSettings
{
public bool disabled { get; set; }
public List<Binding> bindings { get; set; }
}
internal class Binding
{
public string name { get; set; }
public string type { get; set; }
public string direction { get; set; }
public string queueName { get; set; }
public string connection { get; set; }
public string accessRights { get; set; }
}
除了上面@DavidGouge 的回答,他 post 编写的代码确实有效,我刚刚对其进行了测试,并将在我的应用程序中使用它。但是它需要一些调整:
移除对 IFunctionsHelper 的继承。我不确定那个界面是什么,但它不是必需的。
如下更改绑定的 class 定义:
internal class Binding { public string name { get; set; } public string type { get; set; } public string direction { get; set; } public string queueName { get; set; } public string connection { get; set; } public string accessRights { get; set; } public string schedule { get; set; } }
之后就可以了。
P.S。我会把它作为对原始答案的评论,但我在 Stack Overflow 上的声誉不足以 post 评论!
用于通过 CLI 禁用 Azure 功能的 CLI 命令 - 已记录 here
az functionapp config appsettings set --name <myFunctionApp> \
--resource-group <myResourceGroup> \
--settings AzureWebJobs.QueueTrigger.Disabled=true
我在 运行 执行上述命令时捕获了 fiddler。 Azure CLI 在 Python 进程上运行 python 进程正在向
发出请求https://management.azure.com 更新应用程序设置。
在以下 REST 端点中获得了对同一端点的引用: https://docs.microsoft.com/en-us/rest/api/appservice/webapps/updateapplicationsettings
请求 URI :
Headers :
Authorization: Bearer <> ; Content-Type: application/json; charset=utf-8
请求Body:
{"kind": "<class 'str'>", "properties":JSON}
我们可以对属性进行硬编码或动态获取。要禁用该功能,必须更新属性的 JSON 节点:Azure.WebJobs.QueueTrigger.Disabled = True
要获取可以使用端点的属性,您可以参考 Web Apps - List Application Settings 输出如下所示:
希望这对您有所帮助:)
结合使用@Satya V 和@DavidGouge 的解决方案,我想出了这个:
public class FunctionsHelper
{
private readonly ClientSecretCredential _tokenCredential;
private readonly HttpClient _httpClient;
public FunctionsHelper(string tenantId, string clientId, string clientSecret, string subscriptionId, string resourceGroup, string functionAppName)
{
var baseUrl =
$"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Web/sites/{functionAppName}/";
var httpClient = new HttpClient
{
BaseAddress = new Uri(baseUrl)
};
_httpClient = httpClient;
_tokenCredential = new ClientSecretCredential(tenantId, clientId, clientSecret);
}
private async Task SetAuthHeader()
{
var accessToken = await GetAccessToken();
_httpClient.DefaultRequestHeaders.Authorization = AuthenticationHeaderValue.Parse($"Bearer {accessToken}");
}
private async Task<string> GetAccessToken()
{
return (await _tokenCredential.GetTokenAsync(
new TokenRequestContext(new[] {"https://management.azure.com/.default"}))).Token;
}
public async Task StopFunction(string functionName)
{
await SetFunctionState(functionName, isDisabled: true);
}
public async Task StartFunction(string functionName)
{
await SetFunctionState(functionName, isDisabled: false);
}
private async Task SetFunctionState(string functionName, bool isDisabled)
{
await SetAuthHeader();
var appSettings = await GetAppSettings();
appSettings.properties[$"AzureWebJobs.{functionName}.Disabled"] = isDisabled ? "1" : "0";
var payloadJson = JsonConvert.SerializeObject(new
{
kind = "<class 'str'>", appSettings.properties
});
var stringContent = new StringContent(payloadJson, Encoding.UTF8, "application/json");
await _httpClient.PutAsync("config/appsettings?api-version=2019-08-01", stringContent);
}
private async Task<AppSettings> GetAppSettings()
{
var res = await _httpClient.PostAsync("config/appsettings/list?api-version=2019-08-01", null);
var content = await res.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<AppSettings>(content);
}
}
internal class AppSettings
{
public Dictionary<string, string> properties { get; set; }
}
使用 Kudu api 更新 function.json 文件的问题是它会在任何后续部署中被覆盖。这使用 Azure 的 Rest Api 来更新应用程序的配置。不过,您首先需要 Azure 服务原则才能使用 api。
使用 Azure Cli,您可以 运行 az ad sp create-for-rbac
生成服务原则并获取客户端 ID 和客户端密码。因为 UpdateConfiguration 端点不允许您更新单个值,并且会用新值覆盖整个 Configuration 对象,所以您必须首先获取所有当前 Configuration 值,更新您想要的值,然后使用新值调用 Update 端点配置键和值。
这看起来是最简单的本地开发解决方案。