From 74438ee10c342a1345ea56f2d10eb29e922b371a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=A4umlisberger?= Date: Sat, 30 Oct 2021 16:50:53 +0200 Subject: [PATCH] add config element to load environment variables from a file --- doc/xmlConfigFile.md | 8 ++++++ doc/yamlConfigFile.md | 8 ++++++ .../Configuration/DefaultSettings.cs | 2 ++ .../Configuration/XmlServiceConfig.cs | 19 ++++++++++++++ .../Configuration/YamlServiceConfig.cs | 17 +++++++++++++ src/WinSW.Core/Util/ConfigHelper.cs | 25 +++++++++++++++++++ 6 files changed, 79 insertions(+) diff --git a/doc/xmlConfigFile.md b/doc/xmlConfigFile.md index f5536e7..ccbbcab 100644 --- a/doc/xmlConfigFile.md +++ b/doc/xmlConfigFile.md @@ -139,6 +139,14 @@ This optional element can be specified multiple times if necessary to specify en ``` +### Environment File + +This optional element can be specified one time to specify a file to load environment variables from. Each variable definition must be on a separate line and in the format "key=value". Empty lines an lines starting with "#" are ignored. The syntax is: + +```xml +%BASE%/env.txt +``` + ### interactive If this optional element is specified, the service will be allowed to interact with the desktop, such as by showing a new window and dialog boxes. diff --git a/doc/yamlConfigFile.md b/doc/yamlConfigFile.md index 33bd88b..2dc169b 100644 --- a/doc/yamlConfigFile.md +++ b/doc/yamlConfigFile.md @@ -171,6 +171,14 @@ env: value: host1;host2 ``` +### Environment File + +This optional element can be specified one time to specify a file to load environment variables from. Each variable definition must be on a separate line and in the format "key=value". Empty lines an lines starting with "#" are ignored. The syntax is: + +```yaml +envFile: '%BASE%/env.txt' +``` + ### interactive If this optional element is specified, the service will be allowed to interact with the desktop, such as by showing a new window and dialog boxes. diff --git a/src/WinSW.Core/Configuration/DefaultSettings.cs b/src/WinSW.Core/Configuration/DefaultSettings.cs index acabcc7..2025b06 100644 --- a/src/WinSW.Core/Configuration/DefaultSettings.cs +++ b/src/WinSW.Core/Configuration/DefaultSettings.cs @@ -129,6 +129,8 @@ namespace WinSW.Configuration public Dictionary EnvironmentVariables => new(0); + public string? EnvironmentVariablesFile => null; + // Misc public bool BeepOnShutdown => false; diff --git a/src/WinSW.Core/Configuration/XmlServiceConfig.cs b/src/WinSW.Core/Configuration/XmlServiceConfig.cs index b1bbbda..3a26b44 100644 --- a/src/WinSW.Core/Configuration/XmlServiceConfig.cs +++ b/src/WinSW.Core/Configuration/XmlServiceConfig.cs @@ -65,6 +65,8 @@ namespace WinSW // Also inject system environment variables Environment.SetEnvironmentVariable(WinSWSystem.EnvVarNameServiceId, this.Name); + this.LoadEnvironmentVariablesFromFile(); + this.environmentVariables = this.LoadEnvironmentVariables(); } @@ -528,6 +530,11 @@ namespace WinSW /// public Dictionary EnvironmentVariables => new(this.environmentVariables); + /// + /// File from which environment variables are loaded. + /// + public string? EnvironmentVariablesFile => this.SingleElement("envFile", optional: true); + /// /// List of downloads to be performed by the wrapper before starting /// a service. @@ -690,6 +697,18 @@ namespace WinSW return environment; } + private void LoadEnvironmentVariablesFromFile() + { + var envFile = this.SingleElement("envFile", optional: true); + + if (envFile is null) + { + return; + } + + ConfigHelper.LoadEnvironmentVariablesFile(envFile); + } + public List? YamlExtensions => Defaults.YamlExtensions; } } diff --git a/src/WinSW.Core/Configuration/YamlServiceConfig.cs b/src/WinSW.Core/Configuration/YamlServiceConfig.cs index b6613d3..42d8515 100644 --- a/src/WinSW.Core/Configuration/YamlServiceConfig.cs +++ b/src/WinSW.Core/Configuration/YamlServiceConfig.cs @@ -43,6 +43,8 @@ namespace WinSW.Configuration // Also inject system environment variables Environment.SetEnvironmentVariable(WinSWSystem.EnvVarNameServiceId, this.Name); + this.LoadEnvironmentVariablesFromFile(); + this.LoadEnvironmentVariables(); } @@ -201,6 +203,8 @@ namespace WinSW.Configuration public Dictionary EnvironmentVariables { get; set; } = new Dictionary(); + public string? EnvironmentVariablesFile => Expand(this.raw.EnvFile) ?? this.defaults.EnvironmentVariablesFile; + public void LoadEnvironmentVariables() { if (this.raw.Env is null) @@ -224,6 +228,18 @@ namespace WinSW.Configuration } } + private void LoadEnvironmentVariablesFromFile() + { + string? envFile = Expand(this.raw.EnvFile); + + if (envFile is null) + { + return; + } + + ConfigHelper.LoadEnvironmentVariablesFile(envFile); + } + public ServiceAccount ServiceAccount { get @@ -315,6 +331,7 @@ namespace WinSW.Configuration public string? Priority; public string? BeepOnShutdown; public List? Env; + public string? EnvFile; public List? OnFailure; public string? DelayedAutoStart; public string? SecurityDescriptor; diff --git a/src/WinSW.Core/Util/ConfigHelper.cs b/src/WinSW.Core/Util/ConfigHelper.cs index 2ff1978..10a71d0 100644 --- a/src/WinSW.Core/Util/ConfigHelper.cs +++ b/src/WinSW.Core/Util/ConfigHelper.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; namespace WinSW.Util { @@ -45,5 +46,29 @@ namespace WinSW.Util return false; } + + public static void LoadEnvironmentVariablesFile(string envFile) + { + foreach (string line in File.ReadAllLines(envFile)) + { + if (line.Length == 0 || line.StartsWith("#")) + { + // ignore empty lines and comments + continue; + } + + int equalsSignIndex = line.IndexOf("="); + + if (equalsSignIndex == -1) + { + throw new WinSWException("The environment variables file (env-file) contains one or more invalid entries. Each variable definition must be on a separate line and in the format \"key=value\"."); + } + + string key = line.Substring(0, equalsSignIndex); + string value = line.Substring(equalsSignIndex + 1); + + Environment.SetEnvironmentVariable(key, value); + } + } } }