blob: d77f15445ef3690dcbf5a94139ad3412279276c7 [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
37func getProcessParams(process check.Command, service check.Service) ([]string, error) {
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020038 hosts, err := listHosts()
39 if err != nil {
40 return []string{}, err
41 }
42
43 for _, host := range hosts {
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020044 cmd, err := getPsCmdOutput(host, service)
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020045 if err != nil {
46 return []string{}, err
47 }
48
49 if len(cmd) > 0 {
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020050 i := bytes.Index(cmd, []byte(process.String()))
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020051 if i == -1 {
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020052 return []string{}, fmt.Errorf("missing %s command", process)
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020053 }
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020054 return btos(cmd[i+len(process.String()):]), nil
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020055 }
56 }
57 return []string{}, nil
58}
59
60// listHosts lists IDs of active hosts.
61// It queries default environment set in configuration file.
62func listHosts() ([]string, error) {
63 cmd := exec.Command(bin, cmdHosts, cmdHostsParams)
64 out, err := cmd.Output()
65 if err != nil {
66 return nil, err
67 }
68 return btos(out), nil
69}
70
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020071// getPsCmdOutput returns running Kubernetes service command with its parameters.
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020072// It queries default environment set in configuration file.
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020073func getPsCmdOutput(host string, service check.Service) ([]byte, error) {
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020074 // Following is equivalent to:
75 // $ rancher --host $HOST \
76 // docker ps --no-trunc \
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020077 // --filter "label=io.rancher.stack_service.name=$SERVICE" \
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020078 // --format "{{.Command}}"
79 cmd := exec.Command(bin, paramHost, host,
80 cmdDocker, cmdDockerCmdPs, cmdDockerCmdPsParams,
Pawel Wieczorek76dd9bf2019-09-26 16:43:01 +020081 cmdDockerCmdPsFilter, cmdDockerCmdPsFilterArgs+service.String(),
Pawel Wieczorek6b223c92019-05-26 15:35:02 +020082 cmdDockerCmdPsFormat, cmdDockerCmdPsFormatArgs)
83 out, err := cmd.Output()
84 if err != nil {
85 return nil, err
86 }
87 return out, nil
88}
89
90// btos converts slice of bytes to slice of strings split by white space characters.
91func btos(in []byte) []string {
92 var out []string
93 for _, b := range bytes.Fields(in) {
94 out = append(out, string(b))
95 }
96 return out
97}