public async Task <string> GetSyncTriggersPayload() { var hostOptions = _applicationHostOptions.CurrentValue.ToHostOptions(); var functionsMetadata = _functionMetadataProvider.GetFunctionMetadata(); // trigger information used by the ScaleController var triggers = await GetFunctionTriggers(functionsMetadata, hostOptions); var triggersArray = new JArray(triggers); if (!ArmCacheEnabled) { // extended format is disabled - just return triggers return(JsonConvert.SerializeObject(triggersArray)); } // Add triggers to the payload JObject result = new JObject(); result.Add("triggers", triggersArray); // Add functions details to the payload JObject functions = new JObject(); string routePrefix = await WebFunctionsManager.GetRoutePrefix(hostOptions.RootScriptPath); var functionDetails = await WebFunctionsManager.GetFunctionMetadataResponse(functionsMetadata, hostOptions, _hostNameProvider); result.Add("functions", new JArray(functionDetails.Select(p => JObject.FromObject(p)))); // Add functions secrets to the payload // Only secret types we own/control can we cache directly // Encryption is handled by Antares before storage var secretsStorageType = _environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsSecretStorageType); if (string.IsNullOrEmpty(secretsStorageType) || string.Compare(secretsStorageType, "files", StringComparison.OrdinalIgnoreCase) == 0 || string.Compare(secretsStorageType, "blob", StringComparison.OrdinalIgnoreCase) == 0) { JObject secrets = new JObject(); result.Add("secrets", secrets); // add host secrets var hostSecretsInfo = await _secretManagerProvider.Current.GetHostSecretsAsync(); var hostSecrets = new JObject(); hostSecrets.Add("master", hostSecretsInfo.MasterKey); hostSecrets.Add("function", JObject.FromObject(hostSecretsInfo.FunctionKeys)); hostSecrets.Add("system", JObject.FromObject(hostSecretsInfo.SystemKeys)); secrets.Add("host", hostSecrets); // add function secrets var functionSecrets = new JArray(); var httpFunctions = functionsMetadata.Where(p => !p.IsProxy && p.InputBindings.Any(q => q.IsTrigger && string.Compare(q.Type, "httptrigger", StringComparison.OrdinalIgnoreCase) == 0)).Select(p => p.Name); foreach (var functionName in httpFunctions) { var currSecrets = await _secretManagerProvider.Current.GetFunctionSecretsAsync(functionName); var currElement = new JObject() { { "name", functionName }, { "secrets", JObject.FromObject(currSecrets) } }; functionSecrets.Add(currElement); } secrets.Add("function", functionSecrets); } else { // TODO: handle other external key storage types // like KeyVault when the feature comes online } string json = JsonConvert.SerializeObject(result); if (json.Length > ScriptConstants.MaxTriggersStringLength) { // The settriggers call to the FE enforces a max request size // limit. If we're over limit, revert to the minimal triggers // format. _logger.LogWarning($"SyncTriggers payload of length '{json.Length}' exceeds max length of '{ScriptConstants.MaxTriggersStringLength}'. Reverting to minimal format."); return(JsonConvert.SerializeObject(triggersArray)); } return(json); }
public async Task <SyncTriggersPayload> GetSyncTriggersPayload() { var hostOptions = _applicationHostOptions.CurrentValue.ToHostOptions(); var functionsMetadata = _functionMetadataManager.GetFunctionMetadata(); // trigger information used by the ScaleController var triggers = await GetFunctionTriggers(functionsMetadata, hostOptions); var triggersArray = new JArray(triggers); int count = triggersArray.Count; if (!ArmCacheEnabled) { // extended format is disabled - just return triggers return(new SyncTriggersPayload { Content = JsonConvert.SerializeObject(triggersArray), Count = count }); } // Add triggers to the payload JObject result = new JObject(); result.Add("triggers", triggersArray); // Add all listable functions details to the payload JObject functions = new JObject(); string routePrefix = await WebFunctionsManager.GetRoutePrefix(hostOptions.RootScriptPath); var listableFunctions = _functionMetadataManager.GetFunctionMetadata().Where(m => !m.IsCodeless()); var functionDetails = await WebFunctionsManager.GetFunctionMetadataResponse(listableFunctions, hostOptions, _hostNameProvider); result.Add("functions", new JArray(functionDetails.Select(p => JObject.FromObject(p)))); // TEMP: refactor this code to properly add extensions in all scenario(#7394) // Add the host.json extensions to the payload if (_environment.IsKubernetesManagedHosting()) { JObject extensionsPayload = await GetHostJsonExtensionsAsync(_applicationHostOptions, _logger); if (extensionsPayload != null) { result.Add("extensions", extensionsPayload); } } if (_secretManagerProvider.SecretsEnabled) { // Add functions secrets to the payload // Only secret types we own/control can we cache directly // Encryption is handled by Antares before storage var secretsStorageType = _environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsSecretStorageType); if (string.IsNullOrEmpty(secretsStorageType) || string.Equals(secretsStorageType, "files", StringComparison.OrdinalIgnoreCase) || string.Equals(secretsStorageType, "blob", StringComparison.OrdinalIgnoreCase)) { var functionAppSecrets = new FunctionAppSecrets(); // add host secrets var hostSecretsInfo = await _secretManagerProvider.Current.GetHostSecretsAsync(); functionAppSecrets.Host = new FunctionAppSecrets.HostSecrets { Master = hostSecretsInfo.MasterKey, Function = hostSecretsInfo.FunctionKeys, System = hostSecretsInfo.SystemKeys }; // add function secrets var httpFunctions = functionsMetadata.Where(p => p.InputBindings.Any(q => q.IsTrigger && string.Equals(q.Type, "httptrigger", StringComparison.OrdinalIgnoreCase))).Select(p => p.Name).ToArray(); functionAppSecrets.Function = new FunctionAppSecrets.FunctionSecrets[httpFunctions.Length]; for (int i = 0; i < httpFunctions.Length; i++) { var currFunctionName = httpFunctions[i]; var currSecrets = await _secretManagerProvider.Current.GetFunctionSecretsAsync(currFunctionName); functionAppSecrets.Function[i] = new FunctionAppSecrets.FunctionSecrets { Name = currFunctionName, Secrets = currSecrets }; } result.Add("secrets", JObject.FromObject(functionAppSecrets)); } else { // TODO: handle other external key storage types // like KeyVault when the feature comes online } } string json = JsonConvert.SerializeObject(result); if (json.Length > ScriptConstants.MaxTriggersStringLength && !_environment.IsKubernetesManagedHosting()) { // The settriggers call to the FE enforces a max request size // limit. If we're over limit, revert to the minimal triggers // format. _logger.LogWarning($"SyncTriggers payload of length '{json.Length}' exceeds max length of '{ScriptConstants.MaxTriggersStringLength}'. Reverting to minimal format."); return(new SyncTriggersPayload { Content = JsonConvert.SerializeObject(triggersArray), Count = count }); } return(new SyncTriggersPayload { Content = json, Count = count }); }
public async Task <JToken> GetSyncTriggersPayload() { var hostOptions = _applicationHostOptions.CurrentValue.ToHostOptions(); var functionsMetadata = WebFunctionsManager.GetFunctionsMetadata(hostOptions, _workerConfigs, _logger); // trigger information used by the ScaleController var triggers = await GetFunctionTriggers(functionsMetadata, hostOptions); var triggersArray = new JArray(triggers); if (!ArmCacheEnabled) { // extended format is disabled - just return triggers return(triggersArray); } // Add triggers to the payload JObject result = new JObject(); result.Add("triggers", triggersArray); // Add functions details to the payload JObject functions = new JObject(); string routePrefix = await WebFunctionsManager.GetRoutePrefix(hostOptions.RootScriptPath); var functionDetails = await WebFunctionsManager.GetFunctionMetadataResponse(functionsMetadata, hostOptions, _hostNameProvider); result.Add("functions", new JArray(functionDetails.Select(p => JObject.FromObject(p)))); // Add functions secrets to the payload // Only secret types we own/control can we cache directly // Encryption is handled by Antares before storage var secretsStorageType = _environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsSecretStorageType); if (string.IsNullOrEmpty(secretsStorageType) || string.Compare(secretsStorageType, "files", StringComparison.OrdinalIgnoreCase) == 0 || string.Compare(secretsStorageType, "blob", StringComparison.OrdinalIgnoreCase) == 0) { JObject secrets = new JObject(); result.Add("secrets", secrets); // add host secrets var hostSecretsInfo = await _secretManagerProvider.Current.GetHostSecretsAsync(); var hostSecrets = new JObject(); hostSecrets.Add("master", hostSecretsInfo.MasterKey); hostSecrets.Add("function", JObject.FromObject(hostSecretsInfo.FunctionKeys)); hostSecrets.Add("system", JObject.FromObject(hostSecretsInfo.SystemKeys)); secrets.Add("host", hostSecrets); // add function secrets var functionSecrets = new JArray(); var httpFunctions = functionsMetadata.Where(p => !p.IsProxy && p.InputBindings.Any(q => q.IsTrigger && string.Compare(q.Type, "httptrigger", StringComparison.OrdinalIgnoreCase) == 0)).Select(p => p.Name); foreach (var functionName in httpFunctions) { var currSecrets = await _secretManagerProvider.Current.GetFunctionSecretsAsync(functionName); var currElement = new JObject() { { "name", functionName }, { "secrets", JObject.FromObject(currSecrets) } }; functionSecrets.Add(currElement); } secrets.Add("function", functionSecrets); } else { // TODO: handle other external key storage types // like KeyVault when the feature comes online } return(result); }