From 8a336c1b23e295a1b15b35bbf3f4a29db69ffab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Mon, 13 Nov 2023 22:12:36 +0100 Subject: [PATCH 1/8] Implement windows service environment variabls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- cmd/grafana-agent-service/config_windows.go | 10 ++++++++++ cmd/grafana-agent-service/main_windows.go | 7 ++++--- cmd/grafana-agent-service/service.go | 5 +++++ cmd/grafana-agent-service/service_test.go | 11 +++++++++-- cmd/grafana-agent-service/testdata/example_service.go | 4 ++++ docs/sources/flow/setup/install/windows.md | 7 +++++++ .../grafana-agent-flow/windows/install_script.nsis | 9 +++++++++ 7 files changed, 48 insertions(+), 5 deletions(-) diff --git a/cmd/grafana-agent-service/config_windows.go b/cmd/grafana-agent-service/config_windows.go index 961e95ad5e51..d9b191df5e0a 100644 --- a/cmd/grafana-agent-service/config_windows.go +++ b/cmd/grafana-agent-service/config_windows.go @@ -16,6 +16,10 @@ type config struct { // not included. Args []string + // Environment holds arguments to pass to the Grafana Agent binary. os.Environ is + // included. + Environment []string + // WorkingDirectory points to the working directory to run the Grafana Agent // binary from. WorkingDirectory string @@ -42,9 +46,15 @@ func loadConfig() (*config, error) { return nil, fmt.Errorf("failed to retrieve key Arguments: %w", err) } + env, _, err := agentKey.GetStringsValue("Environment") + if err != nil { + return nil, fmt.Errorf("failed to retrieve key Arguments: %w", err) + } + return &config{ ServicePath: servicePath, Args: args, + Environment: env, WorkingDirectory: filepath.Dir(servicePath), }, nil } diff --git a/cmd/grafana-agent-service/main_windows.go b/cmd/grafana-agent-service/main_windows.go index f3660f73e7cc..a94a71228516 100644 --- a/cmd/grafana-agent-service/main_windows.go +++ b/cmd/grafana-agent-service/main_windows.go @@ -29,9 +29,10 @@ func main() { } cfg := serviceManagerConfig{ - Path: managerConfig.ServicePath, - Args: managerConfig.Args, - Dir: managerConfig.WorkingDirectory, + Path: managerConfig.ServicePath, + Args: managerConfig.Args, + Environment: managerConfig.Environment, + Dir: managerConfig.WorkingDirectory, // Send logs directly to the event logger. Stdout: logger, diff --git a/cmd/grafana-agent-service/service.go b/cmd/grafana-agent-service/service.go index 10060e19cc28..c302a98a1a36 100644 --- a/cmd/grafana-agent-service/service.go +++ b/cmd/grafana-agent-service/service.go @@ -24,6 +24,9 @@ type serviceManagerConfig struct { // Args of the binary to run, not including the command itself. Args []string + // Environment of the binary to run, including the command environment itself. + Environment []string + // Dir specifies the working directory to run the binary from. If Dir is // empty, the working directory of the current process is used. Dir string @@ -84,5 +87,7 @@ func (svc *serviceManager) buildCommand(ctx context.Context) *exec.Cmd { cmd.Dir = svc.cfg.Dir cmd.Stdout = svc.cfg.Stdout cmd.Stderr = svc.cfg.Stderr + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, svc.cfg.Environment...) return cmd } diff --git a/cmd/grafana-agent-service/service_test.go b/cmd/grafana-agent-service/service_test.go index d6389132071b..a1d3124b034c 100644 --- a/cmd/grafana-agent-service/service_test.go +++ b/cmd/grafana-agent-service/service_test.go @@ -30,8 +30,9 @@ func Test_serviceManager(t *testing.T) { listenHost := getListenHost(t) mgr := newServiceManager(l, serviceManagerConfig{ - Path: serviceBinary, - Args: []string{"-listen-addr", listenHost}, + Path: serviceBinary, + Args: []string{"-listen-addr", listenHost}, + Environment: []string{"LISTEN=" + listenHost}, }) go mgr.Run(componenttest.TestContext(t)) @@ -40,6 +41,12 @@ func Test_serviceManager(t *testing.T) { require.NoError(t, err) require.Equal(t, []byte("Hello, world!"), resp) }) + + util.Eventually(t, func(t require.TestingT) { + resp, err := makeServiceRequest(listenHost, "/echo/env", nil) + require.NoError(t, err) + require.Contains(t, string(resp), "LISTEN="+listenHost) + }) }) t.Run("terminates service binary", func(t *testing.T) { diff --git a/cmd/grafana-agent-service/testdata/example_service.go b/cmd/grafana-agent-service/testdata/example_service.go index ff11e61dfd85..64808b1b8608 100644 --- a/cmd/grafana-agent-service/testdata/example_service.go +++ b/cmd/grafana-agent-service/testdata/example_service.go @@ -7,6 +7,7 @@ import ( "net" "net/http" "os" + "strings" ) func main() { @@ -46,6 +47,9 @@ func run() error { mux.HandleFunc("/echo/response", func(w http.ResponseWriter, r *http.Request) { _, _ = io.Copy(w, r.Body) }) + mux.HandleFunc("/echo/env", func(w http.ResponseWriter, r *http.Request) { + _, _ = w.Write([]byte(strings.Join(os.Environ(), "\n"))) + }) srv := &http.Server{Handler: mux} _ = srv.Serve(lis) diff --git a/docs/sources/flow/setup/install/windows.md b/docs/sources/flow/setup/install/windows.md index 36eaced3b3d0..f6095454703a 100644 --- a/docs/sources/flow/setup/install/windows.md +++ b/docs/sources/flow/setup/install/windows.md @@ -58,6 +58,13 @@ To do a silent install of Grafana Agent on Windows, perform the following steps. * `/DISABLEREPORTING=` Disable [data collection][]. Default: `no` * `/DISABLEPROFILING=` Disable profiling endpoint. Default: `no` +## Service Configuration + +Grafana Agent is using the Windows Registry `HKLM\Software\Grafana\Grafana Agent Flow` for service configuration. + +* `Arguments` (Type `REG_MULTI_SZ`) Each value represents a binary argument for grafana-agent-flow binary. +* `Environment` (Type `REG_MULTI_SZ`) Each value represents a environment value `KEY=VALUE` for grafana-agent-flow binary. + ## Uninstall You can uninstall Grafana Agent with Windows Remove Programs or `C:\Program Files\Grafana Agent\uninstaller.exe`. Uninstalling Grafana Agent stops the service and removes it from disk. This includes any configuration files in the installation directory. diff --git a/packaging/grafana-agent-flow/windows/install_script.nsis b/packaging/grafana-agent-flow/windows/install_script.nsis index 19f3fc6cd668..d9c4fbdca607 100644 --- a/packaging/grafana-agent-flow/windows/install_script.nsis +++ b/packaging/grafana-agent-flow/windows/install_script.nsis @@ -146,6 +146,15 @@ Function InitializeRegistry Pop $0 # Ignore return result ${EndIf} + # Define the environment key, which holds environment variables to pass to the + # service. + nsExec::ExecToLog 'Reg.exe query "${REGKEY}" /reg:64 /v Environment' + Pop $0 + ${If} $0 == 1 + nsExec::ExecToLog 'Reg.exe add "${REGKEY}" /reg:64 /v Environment /t REG_MULTI_SZ' + Pop $0 # Ignore return result + ${EndIf} + Return FunctionEnd From c96e758be8ccd7140ebdf04263305ffeb885df5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Mon, 13 Nov 2023 22:19:21 +0100 Subject: [PATCH 2/8] Changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92b37f905438..0197dde8a753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,6 +98,8 @@ Main (unreleased) - Added support for replaying not sent data for `loki.write` when WAL is enabled. (@thepalbi) - Added support for unicode strings in `pyroscope.ebpf` python profiles. (@korniltsev) + +- Flow Windows service: Support environment variables. (@jkroepke) - Improved resilience of graph evaluation in presence of slow components. (@thampiotr) From 10c7eb812df95b4868a214a70cf58d6cf493244b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Mon, 13 Nov 2023 22:37:53 +0100 Subject: [PATCH 3/8] Add NSIS argument --- docs/sources/flow/setup/install/windows.md | 1 + packaging/grafana-agent-flow/windows/install_script.nsis | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/sources/flow/setup/install/windows.md b/docs/sources/flow/setup/install/windows.md index f6095454703a..eb9fbe006ed3 100644 --- a/docs/sources/flow/setup/install/windows.md +++ b/docs/sources/flow/setup/install/windows.md @@ -57,6 +57,7 @@ To do a silent install of Grafana Agent on Windows, perform the following steps. * `/CONFIG=` Path to the configuration file. Default: `$INSTDIR\config.river` * `/DISABLEREPORTING=` Disable [data collection][]. Default: `no` * `/DISABLEPROFILING=` Disable profiling endpoint. Default: `no` +* `/ENVIRONMENT="KEY=VALUE\0KEY2=VALUE2"` Define environment variables for Windows Service. Default: `` ## Service Configuration diff --git a/packaging/grafana-agent-flow/windows/install_script.nsis b/packaging/grafana-agent-flow/windows/install_script.nsis index d9c4fbdca607..ff86f5d5a5d6 100644 --- a/packaging/grafana-agent-flow/windows/install_script.nsis +++ b/packaging/grafana-agent-flow/windows/install_script.nsis @@ -31,6 +31,7 @@ OutFile "${OUT}" Var PassedInParameters Var Config Var ConfigFlag +Var Environment Var DisableReporting Var DisableReportingFlag Var DisableProfiling @@ -51,6 +52,7 @@ Section "install" ${GetParameters} $PassedInParameters ${GetOptions} $PassedInParameters "/DISABLEPROFILING=" $DisableProfiling ${GetOptions} $PassedInParameters "/DISABLEREPORTING=" $DisableReporting + ${GetOptions} $PassedInParameters "/ENVIRONMENT=" $Environment ${GetOptions} $PassedInParameters "/CONFIG=" $Config # Calls to functions like nsExec::ExecToLog below push the exit code to the @@ -151,7 +153,7 @@ Function InitializeRegistry nsExec::ExecToLog 'Reg.exe query "${REGKEY}" /reg:64 /v Environment' Pop $0 ${If} $0 == 1 - nsExec::ExecToLog 'Reg.exe add "${REGKEY}" /reg:64 /v Environment /t REG_MULTI_SZ' + nsExec::ExecToLog 'Reg.exe add "${REGKEY}" /reg:64 /v Environment /t REG_MULTI_SZ /d "$Environment"' Pop $0 # Ignore return result ${EndIf} From 2e6ee3e32e73902bbcf3f39e156b89f78cdb40b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Tue, 14 Nov 2023 21:07:03 +0100 Subject: [PATCH 4/8] Always override Environment, since its an expected user input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- packaging/grafana-agent-flow/windows/install_script.nsis | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packaging/grafana-agent-flow/windows/install_script.nsis b/packaging/grafana-agent-flow/windows/install_script.nsis index ff86f5d5a5d6..011e6b59c121 100644 --- a/packaging/grafana-agent-flow/windows/install_script.nsis +++ b/packaging/grafana-agent-flow/windows/install_script.nsis @@ -150,12 +150,8 @@ Function InitializeRegistry # Define the environment key, which holds environment variables to pass to the # service. - nsExec::ExecToLog 'Reg.exe query "${REGKEY}" /reg:64 /v Environment' - Pop $0 - ${If} $0 == 1 - nsExec::ExecToLog 'Reg.exe add "${REGKEY}" /reg:64 /v Environment /t REG_MULTI_SZ /d "$Environment"' - Pop $0 # Ignore return result - ${EndIf} + nsExec::ExecToLog 'Reg.exe add "${REGKEY}" /reg:64 /v Environment /t REG_MULTI_SZ /d "$Environment"' + Pop $0 # Ignore return result Return FunctionEnd From 9a719e457a310781c96f3777520bf1576cd8c1f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Tue, 14 Nov 2023 22:27:37 +0100 Subject: [PATCH 5/8] Update cmd/grafana-agent-service/config_windows.go Co-authored-by: Robert Fratto --- cmd/grafana-agent-service/config_windows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/grafana-agent-service/config_windows.go b/cmd/grafana-agent-service/config_windows.go index d9b191df5e0a..479942a2aa33 100644 --- a/cmd/grafana-agent-service/config_windows.go +++ b/cmd/grafana-agent-service/config_windows.go @@ -48,7 +48,7 @@ func loadConfig() (*config, error) { env, _, err := agentKey.GetStringsValue("Environment") if err != nil { - return nil, fmt.Errorf("failed to retrieve key Arguments: %w", err) + return nil, fmt.Errorf("failed to retrieve key Environment: %w", err) } return &config{ From ea743cffc9cbec28db9737a511d113c7761d61c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Mon, 20 Nov 2023 21:38:16 +0100 Subject: [PATCH 6/8] Update cmd/grafana-agent-service/config_windows.go --- cmd/grafana-agent-service/config_windows.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/grafana-agent-service/config_windows.go b/cmd/grafana-agent-service/config_windows.go index 479942a2aa33..e4d712585986 100644 --- a/cmd/grafana-agent-service/config_windows.go +++ b/cmd/grafana-agent-service/config_windows.go @@ -16,8 +16,9 @@ type config struct { // not included. Args []string - // Environment holds arguments to pass to the Grafana Agent binary. os.Environ is - // included. + // Environment holds environment variables for the Grafana Agent service. + // Each item represents an environment variable in form "key=value". + // All environments variables from the current process with be merged into Environment Environment []string // WorkingDirectory points to the working directory to run the Grafana Agent From a71b20e285554e0731df782cfa742308b3037dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Tue, 21 Nov 2023 18:37:11 +0100 Subject: [PATCH 7/8] Update docs/sources/flow/setup/install/windows.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> --- docs/sources/flow/setup/install/windows.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/flow/setup/install/windows.md b/docs/sources/flow/setup/install/windows.md index e9bf0a0e37db..f9106e5f936f 100644 --- a/docs/sources/flow/setup/install/windows.md +++ b/docs/sources/flow/setup/install/windows.md @@ -61,7 +61,7 @@ To do a silent install of Grafana Agent on Windows, perform the following steps. ## Service Configuration -Grafana Agent is using the Windows Registry `HKLM\Software\Grafana\Grafana Agent Flow` for service configuration. +Grafana Agent uses the Windows Registry `HKLM\Software\Grafana\Grafana Agent Flow` for service configuration. * `Arguments` (Type `REG_MULTI_SZ`) Each value represents a binary argument for grafana-agent-flow binary. * `Environment` (Type `REG_MULTI_SZ`) Each value represents a environment value `KEY=VALUE` for grafana-agent-flow binary. From 7688f8eb734926384429e6e94744c908cdfcdc88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Wed, 22 Nov 2023 19:38:11 +0100 Subject: [PATCH 8/8] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d251f0d70a5..67478fd28990 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ Main (unreleased) - Agent Management: Introduce support for templated configuration. (@jcreixell) +### Enhancements + +- Flow Windows service: Support environment variables. (@jkroepke) + ### Bugfixes - Permit `X-Faro-Session-ID` header in CORS requests for the `faro.receiver` @@ -111,8 +115,6 @@ v0.38.0 (2023-11-21) - Make the result of 'discovery.kubelet' support pods that without ports, such as k8s control plane static pods. (@masonmei) - Added support for unicode strings in `pyroscope.ebpf` python profiles. (@korniltsev) - -- Flow Windows service: Support environment variables. (@jkroepke) - Improved resilience of graph evaluation in presence of slow components. (@thampiotr)