AccidentalFish.ApplicationSupport.Core.Configuration.ApplicationConfiguration.FromXDocumentAsync C# (CSharp) Метод

FromXDocumentAsync() публичный статический Метод

Loads the application configuration from an XML document
public static FromXDocumentAsync ( System.Xml.Linq.XDocument document, ApplicationConfigurationSettings settings, bool checkForMissingSettings, IAsyncConfiguration applicationSecretStore = null, Action verboseLogger = null ) : Task
document System.Xml.Linq.XDocument The document
settings ApplicationConfigurationSettings An optional settings file
checkForMissingSettings bool If set to true then any missing settings generate an exception
applicationSecretStore IAsyncConfiguration Optional secret store to use in addition to the settings
verboseLogger Action Optional verbose logger
Результат Task
        public static async Task<ApplicationConfiguration> FromXDocumentAsync(XDocument document, ApplicationConfigurationSettings settings,
            bool checkForMissingSettings, IAsyncConfiguration applicationSecretStore = null, Action<string> verboseLogger = null)
        {
            if (document.Root == null) return null;
            HashSet<string> secrets = new HashSet<string>();
            
            verboseLogger?.Invoke("Processing settings");
            ApplicationConfiguration configuration = new ApplicationConfiguration();
            IApplicationResourceSettingNameProvider nameProvider = new ApplicationResourceSettingNameProvider();
            IEnumerable<XElement> allDescendants = document.Descendants();
            Regex settingPattern = new Regex(@"(?:\{\{)([^}]*)(?:\}\})");
            foreach (XElement element in allDescendants)
            {
                if (!element.HasElements)
                {
                    Match match = settingPattern.Match(element.Value);
                    string value = element.Value;
                    bool containsSecret = false;
                    while (match.Success)
                    {
                        string settingName = match.Groups[1].Value;
                        ApplicationConfigurationSetting setting;
                        if (!settings.Settings.TryGetValue(settingName, out setting) && checkForMissingSettings)
                        {
                            throw new MissingSettingException();
                        }
                        if (setting != null)
                        {
                            containsSecret |= setting.IsSecret;
                            value = value.Replace($"{{{{{settingName}}}}}", setting.Value);
                        }
                        match = match.NextMatch();
                    }
                    element.Value = value;
                    if (containsSecret)
                    {
                        secrets.Add(value);
                    }
                }
            }
            
            document.Root.XPathSelectElements("infrastructure/sql-server").ToList().ForEach(element =>
            {
                var xfqn = element.Element("fqn");
                if (xfqn != null)
                {
                    var xconnectionstring = element.Element("connection-string");
                    if (xconnectionstring != null)
                        configuration.SqlServerConnectionStrings.Add(xfqn.Value, xconnectionstring.Value);
                }
            });
            document.Root.XPathSelectElements("infrastructure/storage-account").ToList().ForEach(element =>
            {
                ApplicationStorageAccount storageAccount = new ApplicationStorageAccount(element);
                configuration.StorageAccounts.Add(storageAccount.Fqn, storageAccount);
            });
            document.Root.XPathSelectElements("infrastructure/service-bus").ToList().ForEach(element =>
            {
                var xfqn = element.Element("fqn");
                if (xfqn != null)
                {
                    var xconnectionstring = element.Element("connection-string");
                    if (xconnectionstring != null)
                        configuration.ServiceBusConnectionStrings.Add(xfqn.Value, xconnectionstring.Value);
                }
            });

            foreach (XElement element in document.Root.Elements("component").ToList())
            {
                ApplicationComponent component = new ApplicationComponent
                {
                    Fqn = element.Attribute("fqn").Value
                };
                IComponentIdentity componentIdentity = new ComponentIdentity(component.Fqn);
                verboseLogger?.Invoke($"Parsing component {componentIdentity}");

                XElement sqlServerElement = element.Element("sql-server");
                XElement storageElement = element.Element("storage-account");
                XElement serviceBusElement = element.Element("service-bus");
                XElement dbContextTypeElement = element.Element("db-context-type");
                XElement defaultBlobContainerNameElement = element.Element("default-blob-container-name");
                XElement defaultQueueNameElement = element.Element("default-queue-name");
                XElement defaultTableNameElement = element.Element("default-table-name");
                XElement defaultTableData = element.Element("table-data");
                XElement defaultLeaseBlockNameElement = element.Element("default-lease-block-name");
                XElement defaultSubscriptionNameElement = element.Element("default-subscription-name");
                XElement defaultTopicNameElement = element.Element("default-topic-name");
                XElement defaultBrokeredMessageQueueNameElement = element.Element("default-brokered-message-queue-name");
                XElement settingsElement = element.Element("settings");
                XAttribute defaultBlobContainerAccessAttribute = defaultBlobContainerNameElement?.Attribute("public-permission");

                
                if (sqlServerElement != null)
                {
                    try
                    {
                        string secret = applicationSecretStore != null ? await applicationSecretStore.GetAsync(nameProvider.SqlConnectionString(componentIdentity)) : null;
                        component.SqlServerConnectionString = secret ?? configuration.SqlServerConnectionStrings[sqlServerElement.Value];
                    }
                    catch (KeyNotFoundException)
                    {
                        throw new InvalidDataException($"Sql server with fqn of {sqlServerElement.Value} is missing from configuration file.");
                    }
                    
                }
                if (storageElement != null)
                {
                    try
                    {
                        string secret = applicationSecretStore != null ? await applicationSecretStore.GetAsync(nameProvider.StorageAccountConnectionString(componentIdentity)) : null;
                        component.StorageAccountConnectionString = secret ?? configuration.StorageAccounts[storageElement.Value].ConnectionString;
                    }
                    catch (Exception)
                    {
                        throw new InvalidDataException($"Storage account with fqn of {storageElement.Value} is missing from configuration file.");
                    }
                }
                if (serviceBusElement != null)
                {
                    try
                    {
                        verboseLogger?.Invoke($"Looking for service bus connection string for component {componentIdentity}");
                        string secret = applicationSecretStore != null ? await applicationSecretStore.GetAsync(nameProvider.ServiceBusConnectionString(componentIdentity)) : null;                        
                        if (secret != null)
                        {
                            verboseLogger?.Invoke($"Using secret store service bus connection string for component {componentIdentity}");
                        }
                        component.ServiceBusConnectionString = secret ?? configuration.ServiceBusConnectionStrings[serviceBusElement.Value];
                    }
                    catch (Exception)
                    {
                        throw new InvalidDataException($"Service bus account with fqn of {serviceBusElement.Value} is missing from configuration file.");
                    }
                }

                string name = nameProvider.SqlContextType(componentIdentity);
                verboseLogger?.Invoke(name);
                string dbContextTypeSecret = applicationSecretStore != null ? await applicationSecretStore.GetAsync(name) : null;
                if (!string.IsNullOrWhiteSpace(dbContextTypeSecret)) verboseLogger?.Invoke($"Using secret store for dbContextType for component {componentIdentity}");
                component.DbContextType = dbContextTypeSecret ?? dbContextTypeElement?.Value;

                string defaultBlobContainerNameSecret = applicationSecretStore != null ? await applicationSecretStore.GetAsync(nameProvider.DefaultBlobContainerName(componentIdentity)) : null;
                if (!string.IsNullOrWhiteSpace(defaultBlobContainerNameSecret)) verboseLogger?.Invoke($"Using secret store for default blob container name for component {componentIdentity}");
                component.DefaultBlobContainerName = defaultBlobContainerNameSecret ?? defaultBlobContainerNameElement?.Value;

                string defaultQueueNameSecret = applicationSecretStore != null ? await applicationSecretStore.GetAsync(nameProvider.DefaultQueueName(componentIdentity)) : null;
                if (!string.IsNullOrWhiteSpace(defaultQueueNameSecret)) verboseLogger?.Invoke($"Using secret store for default queue name for component {componentIdentity}");
                component.DefaultQueueName = defaultQueueNameSecret ?? defaultQueueNameElement?.Value;

                string defaultTableNameSecret = applicationSecretStore != null ? await applicationSecretStore.GetAsync(nameProvider.DefaultTableName(componentIdentity)) : null;
                if (!string.IsNullOrWhiteSpace(defaultTableNameSecret)) verboseLogger?.Invoke($"Using secret store for default table name for component {componentIdentity}");
                component.DefaultTableName = defaultTableNameSecret ?? defaultTableNameElement?.Value;

                component.DefaultBlobContainerAccessType = BlobContainerPublicAccessTypeEnum.Off;

                string defaultLeaseBlockNameSecret = applicationSecretStore != null ? await applicationSecretStore.GetAsync(nameProvider.DefaultLeaseBlockName(componentIdentity)) : null;
                if (!string.IsNullOrWhiteSpace(defaultLeaseBlockNameSecret)) verboseLogger?.Invoke($"Using secret store for default lease block name for component {componentIdentity}");
                component.DefaultLeaseBlockName = defaultLeaseBlockNameSecret ?? defaultLeaseBlockNameElement?.Value;

                string defaultTopicNameSecret = applicationSecretStore != null ? await applicationSecretStore.GetAsync(nameProvider.DefaultTopicName(componentIdentity)) : null;
                if (!string.IsNullOrWhiteSpace(defaultTopicNameSecret)) verboseLogger?.Invoke($"Using secret store for default topic name for component {componentIdentity}");
                component.DefaultTopicName = defaultTopicNameSecret ?? defaultTopicNameElement?.Value;

                string defaultSubscriptionNameSecret = applicationSecretStore != null ? await applicationSecretStore.GetAsync(nameProvider.DefaultSubscriptionName(componentIdentity)) : null;
                if (!string.IsNullOrWhiteSpace(defaultSubscriptionNameSecret)) verboseLogger?.Invoke($"Using secret store for default subscription name for component {componentIdentity}");
                component.DefaultSubscriptionName = defaultSubscriptionNameSecret ?? defaultSubscriptionNameElement?.Value;

                string defaultBrokeredMessageQueueNameSecret = applicationSecretStore != null ? await applicationSecretStore.GetAsync(nameProvider.DefaultBrokeredMessageQueueName(componentIdentity)) : null;
                if (!string.IsNullOrWhiteSpace(defaultBrokeredMessageQueueNameSecret)) verboseLogger?.Invoke($"Using secret store for default brokered message queue name for component {componentIdentity}");
                component.DefaultBrokeredMessageQueueName = defaultBrokeredMessageQueueNameSecret ?? defaultBrokeredMessageQueueNameElement?.Value;

                component.TableData = defaultTableData?.Value;
                component.Uploads = element.Elements("upload").Select(x => x.Value).ToList();
                if (defaultBlobContainerAccessAttribute != null)
                {
                    string accessAttribtueValue = defaultBlobContainerAccessAttribute.Value.ToLower();
                    if (accessAttribtueValue == "blob")
                    {
                        component.DefaultBlobContainerAccessType = BlobContainerPublicAccessTypeEnum.Blob;
                    }
                    else if (accessAttribtueValue == "container")
                    {
                        component.DefaultBlobContainerAccessType = BlobContainerPublicAccessTypeEnum.Container;
                    }
                }

                verboseLogger?.Invoke($"Processing settings for {componentIdentity}");
                if (settingsElement != null)
                {
                    foreach (XElement componentSettingsElement in settingsElement.Elements().ToList())
                    {
                        string resourceType = null;
                        XAttribute resourceTypeAttr = componentSettingsElement.Attribute("resource-type");
                        if (resourceTypeAttr != null)
                        {
                            resourceType = resourceTypeAttr.Value;
                        }
                        Dictionary<string, string> attributeDictionary = componentSettingsElement.Attributes().ToDictionary(attribute => attribute.Name.LocalName, attribute => attribute.Value);
                        component.Settings.Add(new ApplicationComponentSetting
                        {
                            Key = componentSettingsElement.Name.LocalName,
                            ResourceType = resourceType,
                            Value = (applicationSecretStore != null ? await applicationSecretStore.GetAsync(nameProvider.SettingName(componentIdentity, componentSettingsElement.Name.LocalName)) : null) ?? componentSettingsElement.Value,
                            Attributes = attributeDictionary
                        });
                    }
                }
                
                configuration.ApplicationComponents.Add(component);
                verboseLogger?.Invoke($"Finished parsing component {componentIdentity}");
            }

            configuration.Secrets = secrets.ToList();

            return configuration;
        }
    }