mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-11-01 04:22:36 +08:00 
			
		
		
		
	cmd: Prevent overwriting existing env vars with --envfile (#5803)
				
					
				
			Co-authored-by: Francis Lavoie <lavofr@gmail.com>
This commit is contained in:
		| @ -46,7 +46,14 @@ func cmdStart(fl Flags) (int, error) { | |||||||
| 	startCmdConfigAdapterFlag := fl.String("adapter") | 	startCmdConfigAdapterFlag := fl.String("adapter") | ||||||
| 	startCmdPidfileFlag := fl.String("pidfile") | 	startCmdPidfileFlag := fl.String("pidfile") | ||||||
| 	startCmdWatchFlag := fl.Bool("watch") | 	startCmdWatchFlag := fl.Bool("watch") | ||||||
| 	startCmdEnvfileFlag := fl.String("envfile") |  | ||||||
|  | 	var err error | ||||||
|  | 	var startCmdEnvfileFlag []string | ||||||
|  | 	startCmdEnvfileFlag, err = fl.GetStringSlice("envfile") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return caddy.ExitCodeFailedStartup, | ||||||
|  | 			fmt.Errorf("reading envfile flag: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// open a listener to which the child process will connect when | 	// open a listener to which the child process will connect when | ||||||
| 	// it is ready to confirm that it has successfully started | 	// it is ready to confirm that it has successfully started | ||||||
| @ -70,8 +77,9 @@ func cmdStart(fl Flags) (int, error) { | |||||||
| 	if startCmdConfigFlag != "" { | 	if startCmdConfigFlag != "" { | ||||||
| 		cmd.Args = append(cmd.Args, "--config", startCmdConfigFlag) | 		cmd.Args = append(cmd.Args, "--config", startCmdConfigFlag) | ||||||
| 	} | 	} | ||||||
| 	if startCmdEnvfileFlag != "" { |  | ||||||
| 		cmd.Args = append(cmd.Args, "--envfile", startCmdEnvfileFlag) | 	for _, envFile := range startCmdEnvfileFlag { | ||||||
|  | 		cmd.Args = append(cmd.Args, "--envfile", envFile) | ||||||
| 	} | 	} | ||||||
| 	if startCmdConfigAdapterFlag != "" { | 	if startCmdConfigAdapterFlag != "" { | ||||||
| 		cmd.Args = append(cmd.Args, "--adapter", startCmdConfigAdapterFlag) | 		cmd.Args = append(cmd.Args, "--adapter", startCmdConfigAdapterFlag) | ||||||
| @ -160,15 +168,22 @@ func cmdRun(fl Flags) (int, error) { | |||||||
| 	runCmdConfigFlag := fl.String("config") | 	runCmdConfigFlag := fl.String("config") | ||||||
| 	runCmdConfigAdapterFlag := fl.String("adapter") | 	runCmdConfigAdapterFlag := fl.String("adapter") | ||||||
| 	runCmdResumeFlag := fl.Bool("resume") | 	runCmdResumeFlag := fl.Bool("resume") | ||||||
| 	runCmdLoadEnvfileFlag := fl.String("envfile") |  | ||||||
| 	runCmdPrintEnvFlag := fl.Bool("environ") | 	runCmdPrintEnvFlag := fl.Bool("environ") | ||||||
| 	runCmdWatchFlag := fl.Bool("watch") | 	runCmdWatchFlag := fl.Bool("watch") | ||||||
| 	runCmdPidfileFlag := fl.String("pidfile") | 	runCmdPidfileFlag := fl.String("pidfile") | ||||||
| 	runCmdPingbackFlag := fl.String("pingback") | 	runCmdPingbackFlag := fl.String("pingback") | ||||||
|  |  | ||||||
|  | 	var err error | ||||||
|  | 	var runCmdLoadEnvfileFlag []string | ||||||
|  | 	runCmdLoadEnvfileFlag, err = fl.GetStringSlice("envfile") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return caddy.ExitCodeFailedStartup, | ||||||
|  | 			fmt.Errorf("reading envfile flag: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// load all additional envs as soon as possible | 	// load all additional envs as soon as possible | ||||||
| 	if runCmdLoadEnvfileFlag != "" { | 	for _, envFile := range runCmdLoadEnvfileFlag { | ||||||
| 		if err := loadEnvFromFile(runCmdLoadEnvfileFlag); err != nil { | 		if err := loadEnvFromFile(envFile); err != nil { | ||||||
| 			return caddy.ExitCodeFailedStartup, | 			return caddy.ExitCodeFailedStartup, | ||||||
| 				fmt.Errorf("loading additional environment variables: %v", err) | 				fmt.Errorf("loading additional environment variables: %v", err) | ||||||
| 		} | 		} | ||||||
| @ -181,7 +196,6 @@ func cmdRun(fl Flags) (int, error) { | |||||||
|  |  | ||||||
| 	// load the config, depending on flags | 	// load the config, depending on flags | ||||||
| 	var config []byte | 	var config []byte | ||||||
| 	var err error |  | ||||||
| 	if runCmdResumeFlag { | 	if runCmdResumeFlag { | ||||||
| 		config, err = os.ReadFile(caddy.ConfigAutosavePath) | 		config, err = os.ReadFile(caddy.ConfigAutosavePath) | ||||||
| 		if os.IsNotExist(err) { | 		if os.IsNotExist(err) { | ||||||
| @ -497,18 +511,24 @@ func cmdAdaptConfig(fl Flags) (int, error) { | |||||||
| func cmdValidateConfig(fl Flags) (int, error) { | func cmdValidateConfig(fl Flags) (int, error) { | ||||||
| 	validateCmdConfigFlag := fl.String("config") | 	validateCmdConfigFlag := fl.String("config") | ||||||
| 	validateCmdAdapterFlag := fl.String("adapter") | 	validateCmdAdapterFlag := fl.String("adapter") | ||||||
| 	runCmdLoadEnvfileFlag := fl.String("envfile") |  | ||||||
|  | 	var err error | ||||||
|  | 	var runCmdLoadEnvfileFlag []string | ||||||
|  | 	runCmdLoadEnvfileFlag, err = fl.GetStringSlice("envfile") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return caddy.ExitCodeFailedStartup, | ||||||
|  | 			fmt.Errorf("reading envfile flag: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// load all additional envs as soon as possible | 	// load all additional envs as soon as possible | ||||||
| 	if runCmdLoadEnvfileFlag != "" { | 	for _, envFile := range runCmdLoadEnvfileFlag { | ||||||
| 		if err := loadEnvFromFile(runCmdLoadEnvfileFlag); err != nil { | 		if err := loadEnvFromFile(envFile); err != nil { | ||||||
| 			return caddy.ExitCodeFailedStartup, | 			return caddy.ExitCodeFailedStartup, | ||||||
| 				fmt.Errorf("loading additional environment variables: %v", err) | 				fmt.Errorf("loading additional environment variables: %v", err) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// use default config and ensure a config file is specified | 	// use default config and ensure a config file is specified | ||||||
| 	var err error |  | ||||||
| 	validateCmdConfigFlag, err = configFileWithRespectToDefault(caddy.Log(), validateCmdConfigFlag) | 	validateCmdConfigFlag, err = configFileWithRespectToDefault(caddy.Log(), validateCmdConfigFlag) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return caddy.ExitCodeFailedStartup, err | 		return caddy.ExitCodeFailedStartup, err | ||||||
|  | |||||||
| @ -104,7 +104,7 @@ using 'caddy run' instead to keep it in the foreground. | |||||||
| 		CobraFunc: func(cmd *cobra.Command) { | 		CobraFunc: func(cmd *cobra.Command) { | ||||||
| 			cmd.Flags().StringP("config", "c", "", "Configuration file") | 			cmd.Flags().StringP("config", "c", "", "Configuration file") | ||||||
| 			cmd.Flags().StringP("adapter", "a", "", "Name of config adapter to apply") | 			cmd.Flags().StringP("adapter", "a", "", "Name of config adapter to apply") | ||||||
| 			cmd.Flags().StringP("envfile", "", "", "Environment file to load") | 			cmd.Flags().StringSliceP("envfile", "", []string{}, "Environment file(s) to load") | ||||||
| 			cmd.Flags().BoolP("watch", "w", false, "Reload changed config file automatically") | 			cmd.Flags().BoolP("watch", "w", false, "Reload changed config file automatically") | ||||||
| 			cmd.Flags().StringP("pidfile", "", "", "Path of file to which to write process ID") | 			cmd.Flags().StringP("pidfile", "", "", "Path of file to which to write process ID") | ||||||
| 			cmd.RunE = WrapCommandFuncForCobra(cmdStart) | 			cmd.RunE = WrapCommandFuncForCobra(cmdStart) | ||||||
| @ -150,7 +150,7 @@ option in a local development environment. | |||||||
| 		CobraFunc: func(cmd *cobra.Command) { | 		CobraFunc: func(cmd *cobra.Command) { | ||||||
| 			cmd.Flags().StringP("config", "c", "", "Configuration file") | 			cmd.Flags().StringP("config", "c", "", "Configuration file") | ||||||
| 			cmd.Flags().StringP("adapter", "a", "", "Name of config adapter to apply") | 			cmd.Flags().StringP("adapter", "a", "", "Name of config adapter to apply") | ||||||
| 			cmd.Flags().StringP("envfile", "", "", "Environment file to load") | 			cmd.Flags().StringSliceP("envfile", "", []string{}, "Environment file(s) to load") | ||||||
| 			cmd.Flags().BoolP("environ", "e", false, "Print environment") | 			cmd.Flags().BoolP("environ", "e", false, "Print environment") | ||||||
| 			cmd.Flags().BoolP("resume", "r", false, "Use saved config, if any (and prefer over --config file)") | 			cmd.Flags().BoolP("resume", "r", false, "Use saved config, if any (and prefer over --config file)") | ||||||
| 			cmd.Flags().BoolP("watch", "w", false, "Watch config file for changes and reload it automatically") | 			cmd.Flags().BoolP("watch", "w", false, "Watch config file for changes and reload it automatically") | ||||||
| @ -301,7 +301,7 @@ the KEY=VALUE format will be loaded into the Caddy process. | |||||||
| 		CobraFunc: func(cmd *cobra.Command) { | 		CobraFunc: func(cmd *cobra.Command) { | ||||||
| 			cmd.Flags().StringP("config", "c", "", "Input configuration file") | 			cmd.Flags().StringP("config", "c", "", "Input configuration file") | ||||||
| 			cmd.Flags().StringP("adapter", "a", "", "Name of config adapter") | 			cmd.Flags().StringP("adapter", "a", "", "Name of config adapter") | ||||||
| 			cmd.Flags().StringP("envfile", "", "", "Environment file to load") | 			cmd.Flags().StringSliceP("envfile", "", []string{}, "Environment file(s) to load") | ||||||
| 			cmd.RunE = WrapCommandFuncForCobra(cmdValidateConfig) | 			cmd.RunE = WrapCommandFuncForCobra(cmdValidateConfig) | ||||||
| 		}, | 		}, | ||||||
| 	}) | 	}) | ||||||
| @ -402,7 +402,7 @@ latest versions. EXPERIMENTAL: May be changed or removed. | |||||||
| 		Short: "Adds Caddy packages (EXPERIMENTAL)", | 		Short: "Adds Caddy packages (EXPERIMENTAL)", | ||||||
| 		Long: ` | 		Long: ` | ||||||
| Downloads an updated Caddy binary with the specified packages (module/plugin) | Downloads an updated Caddy binary with the specified packages (module/plugin) | ||||||
| added. Retains existing packages. Returns an error if the any of packages are  | added. Retains existing packages. Returns an error if the any of packages are | ||||||
| already included. EXPERIMENTAL: May be changed or removed. | already included. EXPERIMENTAL: May be changed or removed. | ||||||
| `, | `, | ||||||
| 		CobraFunc: func(cmd *cobra.Command) { | 		CobraFunc: func(cmd *cobra.Command) { | ||||||
| @ -417,8 +417,8 @@ already included. EXPERIMENTAL: May be changed or removed. | |||||||
| 		Usage: "<packages...>", | 		Usage: "<packages...>", | ||||||
| 		Short: "Removes Caddy packages (EXPERIMENTAL)", | 		Short: "Removes Caddy packages (EXPERIMENTAL)", | ||||||
| 		Long: ` | 		Long: ` | ||||||
| Downloads an updated Caddy binaries without the specified packages (module/plugin).  | Downloads an updated Caddy binaries without the specified packages (module/plugin). | ||||||
| Returns an error if any of the packages are not included.  | Returns an error if any of the packages are not included. | ||||||
| EXPERIMENTAL: May be changed or removed. | EXPERIMENTAL: May be changed or removed. | ||||||
| `, | `, | ||||||
| 		CobraFunc: func(cmd *cobra.Command) { | 		CobraFunc: func(cmd *cobra.Command) { | ||||||
| @ -464,40 +464,40 @@ argument of --directory. If the directory does not exist, it will be created. | |||||||
| 		Use:   "completion [bash|zsh|fish|powershell]", | 		Use:   "completion [bash|zsh|fish|powershell]", | ||||||
| 		Short: "Generate completion script", | 		Short: "Generate completion script", | ||||||
| 		Long: fmt.Sprintf(`To load completions: | 		Long: fmt.Sprintf(`To load completions: | ||||||
| 	 |  | ||||||
| 	Bash: | 	Bash: | ||||||
| 	 |  | ||||||
| 	  $ source <(%[1]s completion bash) | 	  $ source <(%[1]s completion bash) | ||||||
| 	 |  | ||||||
| 	  # To load completions for each session, execute once: | 	  # To load completions for each session, execute once: | ||||||
| 	  # Linux: | 	  # Linux: | ||||||
| 	  $ %[1]s completion bash > /etc/bash_completion.d/%[1]s | 	  $ %[1]s completion bash > /etc/bash_completion.d/%[1]s | ||||||
| 	  # macOS: | 	  # macOS: | ||||||
| 	  $ %[1]s completion bash > $(brew --prefix)/etc/bash_completion.d/%[1]s | 	  $ %[1]s completion bash > $(brew --prefix)/etc/bash_completion.d/%[1]s | ||||||
| 	 |  | ||||||
| 	Zsh: | 	Zsh: | ||||||
| 	 |  | ||||||
| 	  # If shell completion is not already enabled in your environment, | 	  # If shell completion is not already enabled in your environment, | ||||||
| 	  # you will need to enable it.  You can execute the following once: | 	  # you will need to enable it.  You can execute the following once: | ||||||
| 	 |  | ||||||
| 	  $ echo "autoload -U compinit; compinit" >> ~/.zshrc | 	  $ echo "autoload -U compinit; compinit" >> ~/.zshrc | ||||||
| 	 |  | ||||||
| 	  # To load completions for each session, execute once: | 	  # To load completions for each session, execute once: | ||||||
| 	  $ %[1]s completion zsh > "${fpath[1]}/_%[1]s" | 	  $ %[1]s completion zsh > "${fpath[1]}/_%[1]s" | ||||||
| 	 |  | ||||||
| 	  # You will need to start a new shell for this setup to take effect. | 	  # You will need to start a new shell for this setup to take effect. | ||||||
| 	 |  | ||||||
| 	fish: | 	fish: | ||||||
| 	 |  | ||||||
| 	  $ %[1]s completion fish | source | 	  $ %[1]s completion fish | source | ||||||
| 	 |  | ||||||
| 	  # To load completions for each session, execute once: | 	  # To load completions for each session, execute once: | ||||||
| 	  $ %[1]s completion fish > ~/.config/fish/completions/%[1]s.fish | 	  $ %[1]s completion fish > ~/.config/fish/completions/%[1]s.fish | ||||||
| 	 |  | ||||||
| 	PowerShell: | 	PowerShell: | ||||||
| 	 |  | ||||||
| 	  PS> %[1]s completion powershell | Out-String | Invoke-Expression | 	  PS> %[1]s completion powershell | Out-String | Invoke-Expression | ||||||
| 	 |  | ||||||
| 	  # To load completions for every new session, run: | 	  # To load completions for every new session, run: | ||||||
| 	  PS> %[1]s completion powershell > %[1]s.ps1 | 	  PS> %[1]s completion powershell > %[1]s.ps1 | ||||||
| 	  # and source this file from your PowerShell profile. | 	  # and source this file from your PowerShell profile. | ||||||
|  | |||||||
| @ -300,8 +300,12 @@ func loadEnvFromFile(envFile string) error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for k, v := range envMap { | 	for k, v := range envMap { | ||||||
| 		if err := os.Setenv(k, v); err != nil { | 		// do not overwrite existing environment variables | ||||||
| 			return fmt.Errorf("setting environment variables: %v", err) | 		_, exists := os.LookupEnv(k) | ||||||
|  | 		if !exists { | ||||||
|  | 			if err := os.Setenv(k, v); err != nil { | ||||||
|  | 				return fmt.Errorf("setting environment variables: %v", err) | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Evan Van Dam
					Evan Van Dam