Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flow Windows service: Support environment variables #5762

Merged
merged 15 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
10 changes: 10 additions & 0 deletions cmd/grafana-agent-service/config_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
jkroepke marked this conversation as resolved.
Show resolved Hide resolved
Environment []string

// WorkingDirectory points to the working directory to run the Grafana Agent
// binary from.
WorkingDirectory string
Expand All @@ -42,9 +46,15 @@ func loadConfig() (*config, error) {
return nil, fmt.Errorf("failed to retrieve key Arguments: %w", err)
}

env, _, err := agentKey.GetStringsValue("Environment")
jkroepke marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, fmt.Errorf("failed to retrieve key Arguments: %w", err)
jkroepke marked this conversation as resolved.
Show resolved Hide resolved
}

return &config{
ServicePath: servicePath,
Args: args,
Environment: env,
WorkingDirectory: filepath.Dir(servicePath),
}, nil
}
7 changes: 4 additions & 3 deletions cmd/grafana-agent-service/main_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions cmd/grafana-agent-service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
11 changes: 9 additions & 2 deletions cmd/grafana-agent-service/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand All @@ -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) {
Expand Down
4 changes: 4 additions & 0 deletions cmd/grafana-agent-service/testdata/example_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"net"
"net/http"
"os"
"strings"
)

func main() {
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions docs/sources/flow/setup/install/windows.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ To do a silent install of Grafana Agent on Windows, perform the following steps.
* `/CONFIG=<path>` Path to the configuration file. Default: `$INSTDIR\config.river`
* `/DISABLEREPORTING=<yes|no>` Disable [data collection][]. Default: `no`
* `/DISABLEPROFILING=<yes|no>` Disable profiling endpoint. Default: `no`
* `/ENVIRONMENT="KEY=VALUE\0KEY2=VALUE2"` Define environment variables for Windows Service. Default: ``

## Service Configuration

Grafana Agent is using the Windows Registry `HKLM\Software\Grafana\Grafana Agent Flow` for service configuration.
jkroepke marked this conversation as resolved.
Show resolved Hide resolved

* `Arguments` (Type `REG_MULTI_SZ`) Each value represents a binary argument for grafana-agent-flow binary.
mattdurham marked this conversation as resolved.
Show resolved Hide resolved
* `Environment` (Type `REG_MULTI_SZ`) Each value represents a environment value `KEY=VALUE` for grafana-agent-flow binary.
Comment on lines +66 to +67
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think people might find it useful if we include a regedit printout of an example configuration. I don't insist on it, will leave it up to you to decide.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean the output of reg query ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess so? I've only used reg export and I suppose reg query does a similar job. As long as people can see the values in a format they can recognise, it's ok.


## Uninstall

Expand Down
11 changes: 11 additions & 0 deletions packaging/grafana-agent-flow/windows/install_script.nsis
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ OutFile "${OUT}"
Var PassedInParameters
Var Config
Var ConfigFlag
Var Environment
Var DisableReporting
Var DisableReportingFlag
Var DisableProfiling
Expand All @@ -51,6 +52,7 @@ Section "install"
${GetParameters} $PassedInParameters
${GetOptions} $PassedInParameters "/DISABLEPROFILING=" $DisableProfiling
${GetOptions} $PassedInParameters "/DISABLEREPORTING=" $DisableReporting
${GetOptions} $PassedInParameters "/ENVIRONMENT=" $Environment
jkroepke marked this conversation as resolved.
Show resolved Hide resolved
${GetOptions} $PassedInParameters "/CONFIG=" $Config

# Calls to functions like nsExec::ExecToLog below push the exit code to the
Expand Down Expand Up @@ -146,6 +148,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 /d "$Environment"'
Pop $0 # Ignore return result
${EndIf}

Return
FunctionEnd

Expand Down