/// <summary> /// Read all functions and populate function metadata. /// </summary> internal ImmutableArray <FunctionMetadata> LoadFunctionMetadata() { ICollection <string> functionsWhiteList = _scriptOptions.Value.Functions; _logger.FunctionMetadataManagerLoadingFunctionsMetadata(); List <FunctionMetadata> functionMetadataList = _functionMetadataProvider.GetFunctionMetadata().ToList(); _functionErrors = _functionMetadataProvider.FunctionErrors.ToDictionary(kvp => kvp.Key, kvp => (ICollection <string>)kvp.Value.ToList()); // Validate foreach (FunctionMetadata functionMetadata in functionMetadataList.ToList()) { if (!IsScriptFileDetermined(functionMetadata)) { // Exclude invalid functions functionMetadataList.Remove(functionMetadata); } } Errors = _functionErrors.ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.ToImmutableArray()); if (functionsWhiteList != null) { _logger.LogInformation($"A function whitelist has been specified, excluding all but the following functions: [{string.Join(", ", functionsWhiteList)}]"); functionMetadataList = functionMetadataList.Where(function => functionsWhiteList.Any(functionName => functionName.Equals(function.Name, StringComparison.CurrentCultureIgnoreCase))).ToList(); Errors = _functionErrors.Where(kvp => functionsWhiteList.Any(functionName => functionName.Equals(kvp.Key, StringComparison.CurrentCultureIgnoreCase))).ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.ToImmutableArray()); } _logger.FunctionMetadataManagerFunctionsLoaded(functionMetadataList.Count()); return(functionMetadataList.ToImmutableArray()); }
internal IEnumerable <FunctionMetadata> GetFunctionsMetadata(ScriptJobHostOptions hostOptions, ILogger logger, bool includeProxies = false) { IEnumerable <FunctionMetadata> functionsMetadata = _functionMetadataProvider.GetFunctionMetadata(); if (includeProxies) { // get proxies metadata var values = ProxyMetadataManager.ReadProxyMetadata(hostOptions.RootScriptPath, logger); var proxyFunctionsMetadata = values.Item1; if (proxyFunctionsMetadata?.Count > 0) { functionsMetadata = proxyFunctionsMetadata.Concat(functionsMetadata); } } return(functionsMetadata); }
/// <summary> /// Read all functions and populate function metadata. /// </summary> internal ImmutableArray <FunctionMetadata> LoadFunctionMetadata(bool forceRefresh = false, bool includeCustomProviders = true) { _functionMetadataMap.Clear(); ICollection <string> functionsAllowList = _scriptOptions?.Value?.Functions; _logger.FunctionMetadataManagerLoadingFunctionsMetadata(); var immutableFunctionMetadata = _functionMetadataProvider.GetFunctionMetadata(_languageWorkerOptions.Value.WorkerConfigs, forceRefresh); var functionMetadataList = new List <FunctionMetadata>(); _functionErrors = new Dictionary <string, ICollection <string> >(); if (!immutableFunctionMetadata.IsDefaultOrEmpty) { functionMetadataList.AddRange(immutableFunctionMetadata); } if (!_functionMetadataProvider.FunctionErrors?.IsEmpty ?? false) { _functionErrors = _functionMetadataProvider.FunctionErrors.ToDictionary(kvp => kvp.Key, kvp => (ICollection <string>)kvp.Value.ToList()); } // Add metadata and errors from any additional function providers if (includeCustomProviders) { LoadCustomProviderFunctions(functionMetadataList); } // Validate foreach (FunctionMetadata functionMetadata in functionMetadataList.ToList()) { if (!IsScriptFileDetermined(functionMetadata)) { // Exclude invalid functions functionMetadataList.Remove(functionMetadata); } } Errors = _functionErrors.ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.ToImmutableArray()); if (functionsAllowList != null) { _logger.LogInformation($"A function allow list has been specified, excluding all but the following functions: [{string.Join(", ", functionsAllowList)}]"); Errors = _functionErrors.Where(kvp => functionsAllowList.Any(functionName => functionName.Equals(kvp.Key, StringComparison.CurrentCultureIgnoreCase))).ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.ToImmutableArray()); } return(functionMetadataList.OrderBy(f => f.Name, StringComparer.OrdinalIgnoreCase).ToImmutableArray()); }
/// <summary> /// Read all functions and populate function metadata. /// </summary> private ImmutableArray <FunctionMetadata> LoadFunctionMetadata() { ICollection <string> functionsWhiteList = _scriptOptions.Value.Functions; _logger.FunctionMetadataManagerLoadingFunctionsMetadata(); ImmutableArray <FunctionMetadata> metadata = _functionMetadataProvider.GetFunctionMetadata(); Errors = _functionMetadataProvider.FunctionErrors; if (functionsWhiteList != null) { _logger.LogInformation($"A function whitelist has been specified, excluding all but the following functions: [{string.Join(", ", functionsWhiteList)}]"); metadata = metadata.Where(function => functionsWhiteList.Any(functionName => functionName.Equals(function.Name, StringComparison.CurrentCultureIgnoreCase))).ToImmutableArray(); Errors = _functionMetadataProvider.FunctionErrors.Where(kvp => functionsWhiteList.Any(functionName => functionName.Equals(kvp.Key, StringComparison.CurrentCultureIgnoreCase))).ToImmutableDictionary <string, ImmutableArray <string> >(); } _logger.FunctionMetadataManagerFunctionsLoaded(metadata.Length); return(metadata); }
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); }