Add option to run varnish under sudo (#3097)
This commit is contained in:
		
							parent
							
								
									cb04fa1e9c
								
							
						
					
					
						commit
						8a2373e8c8
					
				|  | @ -7,6 +7,9 @@ This plugin gathers stats from [Varnish HTTP Cache](https://varnish-cache.org/) | ||||||
| ```toml | ```toml | ||||||
|  # A plugin to collect stats from Varnish HTTP Cache |  # A plugin to collect stats from Varnish HTTP Cache | ||||||
|  [[inputs.varnish]] |  [[inputs.varnish]] | ||||||
|  |    ## If running as a restricted user you can prepend sudo for additional access: | ||||||
|  |    #use_sudo = false | ||||||
|  | 
 | ||||||
|    ## The default location of the varnishstat binary can be overridden with: |    ## The default location of the varnishstat binary can be overridden with: | ||||||
|    binary = "/usr/bin/varnishstat" |    binary = "/usr/bin/varnishstat" | ||||||
| 
 | 
 | ||||||
|  | @ -330,6 +333,63 @@ the following values: | ||||||
|   - LCK |   - LCK | ||||||
|    |    | ||||||
|    |    | ||||||
|  | 
 | ||||||
|  | ### Permissions: | ||||||
|  | 
 | ||||||
|  | It's important to note that this plugin references varnishstat, which may require additional permissions to execute successfully. | ||||||
|  | Depending on the user/group permissions of the telegraf user executing this plugin, you may need to alter the group membership, set facls, or use sudo. | ||||||
|  | 
 | ||||||
|  | **Group membership (Recommended)**: | ||||||
|  | ```bash | ||||||
|  | $ groups telegraf | ||||||
|  | telegraf : telegraf | ||||||
|  | 
 | ||||||
|  | $ usermod -a -G varnish telegraf | ||||||
|  | 
 | ||||||
|  | $ groups telegraf | ||||||
|  | telegraf : telegraf varnish | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | **Extended filesystem ACL's**: | ||||||
|  | ```bash | ||||||
|  | $ getfacl /var/lib/varnish/<hostname>/_.vsm | ||||||
|  | # file: var/lib/varnish/<hostname>/_.vsm | ||||||
|  | # owner: root | ||||||
|  | # group: root | ||||||
|  | user::rw- | ||||||
|  | group::r-- | ||||||
|  | other::--- | ||||||
|  | 
 | ||||||
|  | $ setfacl -m u:telegraf:r /var/lib/varnish/<hostname>/_.vsm | ||||||
|  | 
 | ||||||
|  | $ getfacl /var/lib/varnish/<hostname>/_.vsm | ||||||
|  | # file: var/lib/varnish/<hostname>/_.vsm | ||||||
|  | # owner: root | ||||||
|  | # group: root | ||||||
|  | user::rw- | ||||||
|  | user:telegraf:r-- | ||||||
|  | group::r-- | ||||||
|  | mask::r-- | ||||||
|  | other::--- | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | **Sudo privileges**: | ||||||
|  | ```bash | ||||||
|  | # If you use this method, you will need the following in your telegraf config: | ||||||
|  | [[inputs.varnish]] | ||||||
|  |   use_sudo = true | ||||||
|  | 
 | ||||||
|  | $ visudo | ||||||
|  | 
 | ||||||
|  | # Add the following line: | ||||||
|  | telegraf ALL=(ALL) NOPASSWD: /usr/bin/varnishstat | ||||||
|  | 
 | ||||||
|  | $ grep varnish /etc/sudoers | ||||||
|  | telegraf ALL = NOPASSWD: /usr/bin/varnishstat | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Please use the solution you see as most appropriate. | ||||||
|  | 
 | ||||||
| ### Example Output: | ### Example Output: | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  | @ -17,12 +17,13 @@ import ( | ||||||
| 	"github.com/influxdata/telegraf/plugins/inputs" | 	"github.com/influxdata/telegraf/plugins/inputs" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type runner func(cmdName string) (*bytes.Buffer, error) | type runner func(cmdName string, UseSudo bool) (*bytes.Buffer, error) | ||||||
| 
 | 
 | ||||||
| // Varnish is used to store configuration values
 | // Varnish is used to store configuration values
 | ||||||
| type Varnish struct { | type Varnish struct { | ||||||
| 	Stats  []string | 	Stats   []string | ||||||
| 	Binary string | 	Binary  string | ||||||
|  | 	UseSudo bool | ||||||
| 
 | 
 | ||||||
| 	filter filter.Filter | 	filter filter.Filter | ||||||
| 	run    runner | 	run    runner | ||||||
|  | @ -32,6 +33,9 @@ var defaultStats = []string{"MAIN.cache_hit", "MAIN.cache_miss", "MAIN.uptime"} | ||||||
| var defaultBinary = "/usr/bin/varnishstat" | var defaultBinary = "/usr/bin/varnishstat" | ||||||
| 
 | 
 | ||||||
| var sampleConfig = ` | var sampleConfig = ` | ||||||
|  |   ## If running as a restricted user you can prepend sudo for additional access: | ||||||
|  |   #use_sudo = false | ||||||
|  | 
 | ||||||
|   ## The default location of the varnishstat binary can be overridden with: |   ## The default location of the varnishstat binary can be overridden with: | ||||||
|   binary = "/usr/bin/varnishstat" |   binary = "/usr/bin/varnishstat" | ||||||
| 
 | 
 | ||||||
|  | @ -52,10 +56,16 @@ func (s *Varnish) SampleConfig() string { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Shell out to varnish_stat and return the output
 | // Shell out to varnish_stat and return the output
 | ||||||
| func varnishRunner(cmdName string) (*bytes.Buffer, error) { | func varnishRunner(cmdName string, UseSudo bool) (*bytes.Buffer, error) { | ||||||
| 	cmdArgs := []string{"-1"} | 	cmdArgs := []string{"-1"} | ||||||
| 
 |  | ||||||
| 	cmd := exec.Command(cmdName, cmdArgs...) | 	cmd := exec.Command(cmdName, cmdArgs...) | ||||||
|  | 
 | ||||||
|  | 	if UseSudo { | ||||||
|  | 		cmdArgs = append([]string{cmdName}, cmdArgs...) | ||||||
|  | 		cmdArgs = append([]string{"-n"}, cmdArgs...) | ||||||
|  | 		cmd = exec.Command("sudo", cmdArgs...) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	var out bytes.Buffer | 	var out bytes.Buffer | ||||||
| 	cmd.Stdout = &out | 	cmd.Stdout = &out | ||||||
| 	err := internal.RunTimeout(cmd, time.Millisecond*200) | 	err := internal.RunTimeout(cmd, time.Millisecond*200) | ||||||
|  | @ -89,7 +99,7 @@ func (s *Varnish) Gather(acc telegraf.Accumulator) error { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	out, err := s.run(s.Binary) | 	out, err := s.run(s.Binary, s.UseSudo) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("error gathering metrics: %s", err) | 		return fmt.Errorf("error gathering metrics: %s", err) | ||||||
| 	} | 	} | ||||||
|  | @ -145,9 +155,10 @@ func (s *Varnish) Gather(acc telegraf.Accumulator) error { | ||||||
| func init() { | func init() { | ||||||
| 	inputs.Add("varnish", func() telegraf.Input { | 	inputs.Add("varnish", func() telegraf.Input { | ||||||
| 		return &Varnish{ | 		return &Varnish{ | ||||||
| 			run:    varnishRunner, | 			run:     varnishRunner, | ||||||
| 			Stats:  defaultStats, | 			Stats:   defaultStats, | ||||||
| 			Binary: defaultBinary, | 			Binary:  defaultBinary, | ||||||
|  | 			UseSudo: false, | ||||||
| 		} | 		} | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -11,8 +11,8 @@ import ( | ||||||
| 	"testing" | 	"testing" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func fakeVarnishStat(output string) func(string) (*bytes.Buffer, error) { | func fakeVarnishStat(output string, useSudo bool) func(string, bool) (*bytes.Buffer, error) { | ||||||
| 	return func(string) (*bytes.Buffer, error) { | 	return func(string, bool) (*bytes.Buffer, error) { | ||||||
| 		return bytes.NewBuffer([]byte(output)), nil | 		return bytes.NewBuffer([]byte(output)), nil | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -20,7 +20,7 @@ func fakeVarnishStat(output string) func(string) (*bytes.Buffer, error) { | ||||||
| func TestGather(t *testing.T) { | func TestGather(t *testing.T) { | ||||||
| 	acc := &testutil.Accumulator{} | 	acc := &testutil.Accumulator{} | ||||||
| 	v := &Varnish{ | 	v := &Varnish{ | ||||||
| 		run:   fakeVarnishStat(smOutput), | 		run:   fakeVarnishStat(smOutput, false), | ||||||
| 		Stats: []string{"*"}, | 		Stats: []string{"*"}, | ||||||
| 	} | 	} | ||||||
| 	v.Gather(acc) | 	v.Gather(acc) | ||||||
|  | @ -36,7 +36,7 @@ func TestGather(t *testing.T) { | ||||||
| func TestParseFullOutput(t *testing.T) { | func TestParseFullOutput(t *testing.T) { | ||||||
| 	acc := &testutil.Accumulator{} | 	acc := &testutil.Accumulator{} | ||||||
| 	v := &Varnish{ | 	v := &Varnish{ | ||||||
| 		run:   fakeVarnishStat(fullOutput), | 		run:   fakeVarnishStat(fullOutput, true), | ||||||
| 		Stats: []string{"*"}, | 		Stats: []string{"*"}, | ||||||
| 	} | 	} | ||||||
| 	err := v.Gather(acc) | 	err := v.Gather(acc) | ||||||
|  | @ -51,7 +51,7 @@ func TestParseFullOutput(t *testing.T) { | ||||||
| func TestFilterSomeStats(t *testing.T) { | func TestFilterSomeStats(t *testing.T) { | ||||||
| 	acc := &testutil.Accumulator{} | 	acc := &testutil.Accumulator{} | ||||||
| 	v := &Varnish{ | 	v := &Varnish{ | ||||||
| 		run:   fakeVarnishStat(fullOutput), | 		run:   fakeVarnishStat(fullOutput, false), | ||||||
| 		Stats: []string{"MGT.*", "VBE.*"}, | 		Stats: []string{"MGT.*", "VBE.*"}, | ||||||
| 	} | 	} | ||||||
| 	err := v.Gather(acc) | 	err := v.Gather(acc) | ||||||
|  | @ -74,7 +74,7 @@ func TestFieldConfig(t *testing.T) { | ||||||
| 	for fieldCfg, expected := range expect { | 	for fieldCfg, expected := range expect { | ||||||
| 		acc := &testutil.Accumulator{} | 		acc := &testutil.Accumulator{} | ||||||
| 		v := &Varnish{ | 		v := &Varnish{ | ||||||
| 			run:   fakeVarnishStat(fullOutput), | 			run:   fakeVarnishStat(fullOutput, true), | ||||||
| 			Stats: strings.Split(fieldCfg, ","), | 			Stats: strings.Split(fieldCfg, ","), | ||||||
| 		} | 		} | ||||||
| 		err := v.Gather(acc) | 		err := v.Gather(acc) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue