mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-15 23:06:38 +00:00
[client] Allow clearing saved service env vars with --service-env "" (#5893)
This commit is contained in:
@@ -48,6 +48,8 @@ func init() {
|
|||||||
rootCmd.PersistentFlags().StringVarP(&serviceName, "service", "s", defaultServiceName, "Netbird system service name")
|
rootCmd.PersistentFlags().StringVarP(&serviceName, "service", "s", defaultServiceName, "Netbird system service name")
|
||||||
serviceEnvDesc := `Sets extra environment variables for the service. ` +
|
serviceEnvDesc := `Sets extra environment variables for the service. ` +
|
||||||
`You can specify a comma-separated list of KEY=VALUE pairs. ` +
|
`You can specify a comma-separated list of KEY=VALUE pairs. ` +
|
||||||
|
`New keys are merged with previously saved env vars; existing keys are overwritten. ` +
|
||||||
|
`Use --service-env "" to clear all saved env vars. ` +
|
||||||
`E.g. --service-env NB_LOG_LEVEL=debug,CUSTOM_VAR=value`
|
`E.g. --service-env NB_LOG_LEVEL=debug,CUSTOM_VAR=value`
|
||||||
|
|
||||||
installCmd.Flags().StringSliceVar(&serviceEnvVars, "service-env", nil, serviceEnvDesc)
|
installCmd.Flags().StringSliceVar(&serviceEnvVars, "service-env", nil, serviceEnvDesc)
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ func currentServiceParams() *serviceParams {
|
|||||||
|
|
||||||
if len(serviceEnvVars) > 0 {
|
if len(serviceEnvVars) > 0 {
|
||||||
parsed, err := parseServiceEnvVars(serviceEnvVars)
|
parsed, err := parseServiceEnvVars(serviceEnvVars)
|
||||||
if err == nil && len(parsed) > 0 {
|
if err == nil {
|
||||||
params.ServiceEnvVars = parsed
|
params.ServiceEnvVars = parsed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,27 +146,38 @@ func applyServiceParams(cmd *cobra.Command, params *serviceParams) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// applyServiceEnvParams merges saved service environment variables.
|
// applyServiceEnvParams merges saved service environment variables.
|
||||||
// If --service-env was explicitly set, explicit values win on key conflict
|
// If --service-env was explicitly set with values, explicit values win on key
|
||||||
// but saved keys not in the explicit set are carried over.
|
// conflict but saved keys not in the explicit set are carried over.
|
||||||
|
// If --service-env was explicitly set to empty, all saved env vars are cleared.
|
||||||
// If --service-env was not set, saved env vars are used entirely.
|
// If --service-env was not set, saved env vars are used entirely.
|
||||||
func applyServiceEnvParams(cmd *cobra.Command, params *serviceParams) {
|
func applyServiceEnvParams(cmd *cobra.Command, params *serviceParams) {
|
||||||
if len(params.ServiceEnvVars) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !cmd.Flags().Changed("service-env") {
|
if !cmd.Flags().Changed("service-env") {
|
||||||
|
if len(params.ServiceEnvVars) > 0 {
|
||||||
// No explicit env vars: rebuild serviceEnvVars from saved params.
|
// No explicit env vars: rebuild serviceEnvVars from saved params.
|
||||||
serviceEnvVars = envMapToSlice(params.ServiceEnvVars)
|
serviceEnvVars = envMapToSlice(params.ServiceEnvVars)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicit env vars were provided: merge saved values underneath.
|
// Flag was explicitly set: parse what the user provided.
|
||||||
explicit, err := parseServiceEnvVars(serviceEnvVars)
|
explicit, err := parseServiceEnvVars(serviceEnvVars)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.PrintErrf("Warning: parse explicit service env vars for merge: %v\n", err)
|
cmd.PrintErrf("Warning: parse explicit service env vars for merge: %v\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the user passed an empty value (e.g. --service-env ""), clear all
|
||||||
|
// saved env vars rather than merging.
|
||||||
|
if len(explicit) == 0 {
|
||||||
|
serviceEnvVars = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(params.ServiceEnvVars) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge saved values underneath explicit ones.
|
||||||
merged := make(map[string]string, len(params.ServiceEnvVars)+len(explicit))
|
merged := make(map[string]string, len(params.ServiceEnvVars)+len(explicit))
|
||||||
maps.Copy(merged, params.ServiceEnvVars)
|
maps.Copy(merged, params.ServiceEnvVars)
|
||||||
maps.Copy(merged, explicit) // explicit wins on conflict
|
maps.Copy(merged, explicit) // explicit wins on conflict
|
||||||
|
|||||||
@@ -327,6 +327,41 @@ func TestApplyServiceEnvParams_NotChanged(t *testing.T) {
|
|||||||
assert.Equal(t, map[string]string{"FROM_SAVED": "val"}, result)
|
assert.Equal(t, map[string]string{"FROM_SAVED": "val"}, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestApplyServiceEnvParams_ExplicitEmptyClears(t *testing.T) {
|
||||||
|
origServiceEnvVars := serviceEnvVars
|
||||||
|
t.Cleanup(func() { serviceEnvVars = origServiceEnvVars })
|
||||||
|
|
||||||
|
// Simulate --service-env "" which produces [""] in the slice.
|
||||||
|
serviceEnvVars = []string{""}
|
||||||
|
|
||||||
|
cmd := &cobra.Command{}
|
||||||
|
cmd.Flags().StringSlice("service-env", nil, "")
|
||||||
|
require.NoError(t, cmd.Flags().Set("service-env", ""))
|
||||||
|
|
||||||
|
saved := &serviceParams{
|
||||||
|
ServiceEnvVars: map[string]string{"OLD_VAR": "should_be_cleared"},
|
||||||
|
}
|
||||||
|
|
||||||
|
applyServiceEnvParams(cmd, saved)
|
||||||
|
|
||||||
|
assert.Nil(t, serviceEnvVars, "explicit empty --service-env should clear all saved env vars")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCurrentServiceParams_EmptyEnvVarsAfterParse(t *testing.T) {
|
||||||
|
origServiceEnvVars := serviceEnvVars
|
||||||
|
t.Cleanup(func() { serviceEnvVars = origServiceEnvVars })
|
||||||
|
|
||||||
|
// Simulate --service-env "" which produces [""] in the slice.
|
||||||
|
serviceEnvVars = []string{""}
|
||||||
|
|
||||||
|
params := currentServiceParams()
|
||||||
|
|
||||||
|
// After parsing, the empty string is skipped, resulting in an empty map.
|
||||||
|
// The map should still be set (not nil) so it overwrites saved values.
|
||||||
|
assert.NotNil(t, params.ServiceEnvVars, "empty env vars should produce empty map, not nil")
|
||||||
|
assert.Empty(t, params.ServiceEnvVars, "no valid env vars should be parsed from empty string")
|
||||||
|
}
|
||||||
|
|
||||||
// TestServiceParams_FieldsCoveredInFunctions ensures that all serviceParams fields are
|
// TestServiceParams_FieldsCoveredInFunctions ensures that all serviceParams fields are
|
||||||
// referenced in both currentServiceParams() and applyServiceParams(). If a new field is
|
// referenced in both currentServiceParams() and applyServiceParams(). If a new field is
|
||||||
// added to serviceParams but not wired into these functions, this test fails.
|
// added to serviceParams but not wired into these functions, this test fails.
|
||||||
|
|||||||
Reference in New Issue
Block a user