-
Notifications
You must be signed in to change notification settings - Fork 341
/
nodes.go
107 lines (92 loc) · 3.02 KB
/
nodes.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/*
Copyright 2018 Heptio Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package discovery
import (
"context"
"encoding/json"
"os"
"path"
"time"
"github.com/heptio/sonobuoy/pkg/config"
"github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/rest"
)
type nodeData struct {
APIResource v1.Node `json:"apiResource,omitempty"`
ConfigzOutput map[string]interface{} `json:"configzOutput,omitempty"`
HealthzStatus int `json:"healthzStatus,omitempty"`
}
// getNodeEndpoint returns the response from pinging a node endpoint
func getNodeEndpoint(client rest.Interface, nodeName, endpoint string) (rest.Result, error) {
// TODO(chuckha) make this timeout configurable
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(30*time.Second))
defer cancel()
req := client.
Get().
Context(ctx).
Resource("nodes").
Name(nodeName).
SubResource("proxy").
Suffix(endpoint)
result := req.Do()
if result.Error() != nil {
logrus.Warningf("Could not get %v endpoint for node %v: %v", endpoint, nodeName, result.Error())
}
return result, result.Error()
}
// gatherNodeData collects non-resource information about a node through the
// kubernetes API. That is, its `healthz` and `configz` endpoints, which are
// not "resources" per se, although they are accessible through the apiserver.
func gatherNodeData(nodeNames []string, restclient rest.Interface, cfg *config.Config) error {
logrus.Info("Collecting Node Configuration and Health...")
for _, name := range nodeNames {
// Create the output for each node
out := path.Join(cfg.OutputDir(), HostsLocation, name)
logrus.Infof("Creating host results for %v under %v\n", name, out)
if err := os.MkdirAll(out, 0755); err != nil {
return err
}
_, err := timedObjectQuery(out, "configz.json", func() (interface{}, error) {
data := make(map[string]interface{})
result, err := getNodeEndpoint(restclient, name, "configz")
if err != nil {
return data, err
}
resultBytes, err := result.Raw()
if err != nil {
return data, err
}
json.Unmarshal(resultBytes, &data)
return data, err
})
if err != nil {
return err
}
_, err = timedObjectQuery(out, "healthz.json", func() (interface{}, error) {
data := make(map[string]interface{})
result, err := getNodeEndpoint(restclient, name, "healthz")
if err != nil {
return data, err
}
var healthstatus int
result.StatusCode(&healthstatus)
data["status"] = healthstatus
return data, nil
})
if err != nil {
return err
}
}
return nil
}