blob: 41f3c38e2c8b5fb9942fa38218af01b16b77e367 [file] [log] [blame]
Pawel Wieczorek6b223c92019-05-26 15:35:02 +02001// Package rancher wraps Rancher commands necessary for K8s inspection.
2package rancher
3
4import (
5 "bytes"
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +02006 "fmt"
Pawel Wieczorek6b223c92019-05-26 15:35:02 +02007 "os/exec"
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +02008
9 "check"
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020010)
11
12const (
13 bin = "rancher"
14 paramHost = "--host"
15 cmdHosts = "hosts"
16 cmdHostsParams = "--quiet"
17 cmdDocker = "docker"
18 cmdDockerCmdPs = "ps"
19 cmdDockerCmdPsParams = "--no-trunc"
20 cmdDockerCmdPsFilter = "--filter"
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020021 cmdDockerCmdPsFilterArgs = "label=io.rancher.stack_service.name="
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020022 cmdDockerCmdPsFormat = "--format"
23 cmdDockerCmdPsFormatArgs = "{{.Command}}"
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020024)
25
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020026// Rancher implements Informer interface.
27type Rancher struct {
28 check.Informer
29}
30
31// GetAPIParams returns parameters of running Kubernetes API server.
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020032// It queries default environment set in configuration file.
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020033func (r *Rancher) GetAPIParams() ([]string, error) {
34 return getProcessParams(check.APIProcess, check.APIService)
35}
36
Pawel Wieczorek96f4e2f2019-09-27 16:10:33 +020037// GetSchedulerParams returns parameters of running Kubernetes scheduler.
38// It queries default environment set in configuration file.
39func (r *Rancher) GetSchedulerParams() ([]string, error) {
40 return getProcessParams(check.SchedulerProcess, check.SchedulerService)
41}
42
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020043func getProcessParams(process check.Command, service check.Service) ([]string, error) {
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020044 hosts, err := listHosts()
45 if err != nil {
46 return []string{}, err
47 }
48
49 for _, host := range hosts {
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020050 cmd, err := getPsCmdOutput(host, service)
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020051 if err != nil {
52 return []string{}, err
53 }
54
55 if len(cmd) > 0 {
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020056 i := bytes.Index(cmd, []byte(process.String()))
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020057 if i == -1 {
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020058 return []string{}, fmt.Errorf("missing %s command", process)
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020059 }
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020060 return btos(cmd[i+len(process.String()):]), nil
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020061 }
62 }
63 return []string{}, nil
64}
65
66// listHosts lists IDs of active hosts.
67// It queries default environment set in configuration file.
68func listHosts() ([]string, error) {
69 cmd := exec.Command(bin, cmdHosts, cmdHostsParams)
70 out, err := cmd.Output()
71 if err != nil {
72 return nil, err
73 }
74 return btos(out), nil
75}
76
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020077// getPsCmdOutput returns running Kubernetes service command with its parameters.
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020078// It queries default environment set in configuration file.
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020079func getPsCmdOutput(host string, service check.Service) ([]byte, error) {
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020080 // Following is equivalent to:
81 // $ rancher --host $HOST \
82 // docker ps --no-trunc \
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020083 // --filter "label=io.rancher.stack_service.name=$SERVICE" \
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020084 // --format "{{.Command}}"
85 cmd := exec.Command(bin, paramHost, host,
86 cmdDocker, cmdDockerCmdPs, cmdDockerCmdPsParams,
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020087 cmdDockerCmdPsFilter, cmdDockerCmdPsFilterArgs+service.String(),
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020088 cmdDockerCmdPsFormat, cmdDockerCmdPsFormatArgs)
89 out, err := cmd.Output()
90 if err != nil {
91 return nil, err
92 }
93 return out, nil
94}
95
96// btos converts slice of bytes to slice of strings split by white space characters.
97func btos(in []byte) []string {
98 var out []string
99 for _, b := range bytes.Fields(in) {
100 out = append(out, string(b))
101 }
102 return out
103}