...
1
16
17 package componentstatus
18
19 import (
20 "context"
21 "fmt"
22 "sync"
23
24 "k8s.io/apimachinery/pkg/fields"
25 "k8s.io/apimachinery/pkg/labels"
26 "k8s.io/apiserver/pkg/registry/generic"
27 "k8s.io/apiserver/pkg/storage"
28
29 metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
30 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31 "k8s.io/apimachinery/pkg/runtime"
32 "k8s.io/apiserver/pkg/registry/rest"
33 api "k8s.io/kubernetes/pkg/apis/core"
34 "k8s.io/kubernetes/pkg/printers"
35 printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
36 printerstorage "k8s.io/kubernetes/pkg/printers/storage"
37 "k8s.io/kubernetes/pkg/probe"
38 )
39
40 type REST struct {
41 GetServersToValidate func() map[string]Server
42 rest.TableConvertor
43 }
44
45
46 func NewStorage(serverRetriever func() map[string]Server) *REST {
47 return &REST{
48 GetServersToValidate: serverRetriever,
49 TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
50 }
51 }
52
53 func (*REST) NamespaceScoped() bool {
54 return false
55 }
56
57 func (rs *REST) New() runtime.Object {
58 return &api.ComponentStatus{}
59 }
60
61 var _ rest.SingularNameProvider = &REST{}
62
63 func (rs *REST) GetSingularName() string {
64 return "componentstatus"
65 }
66
67
68 func (r *REST) Destroy() {
69
70
71 }
72
73 func (rs *REST) NewList() runtime.Object {
74 return &api.ComponentStatusList{}
75 }
76
77
78
79 func (rs *REST) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) {
80 servers := rs.GetServersToValidate()
81
82 wait := sync.WaitGroup{}
83 wait.Add(len(servers))
84 statuses := make(chan api.ComponentStatus, len(servers))
85 for k, v := range servers {
86 go func(name string, server Server) {
87 defer wait.Done()
88 status := rs.getComponentStatus(name, server)
89 statuses <- *status
90 }(k, v)
91 }
92 wait.Wait()
93 close(statuses)
94
95 pred := componentStatusPredicate(options)
96
97 reply := []api.ComponentStatus{}
98 for status := range statuses {
99
100
101
102 if matched := matchesPredicate(status, &pred); matched {
103 reply = append(reply, status)
104 }
105 }
106 return &api.ComponentStatusList{Items: reply}, nil
107 }
108
109 func componentStatusPredicate(options *metainternalversion.ListOptions) storage.SelectionPredicate {
110 pred := storage.SelectionPredicate{
111 Label: labels.Everything(),
112 Field: fields.Everything(),
113 GetAttrs: nil,
114 }
115 if options != nil {
116 if options.LabelSelector != nil {
117 pred.Label = options.LabelSelector
118 }
119 if options.FieldSelector != nil {
120 pred.Field = options.FieldSelector
121 }
122 }
123 return pred
124 }
125
126 func matchesPredicate(status api.ComponentStatus, pred *storage.SelectionPredicate) bool {
127
128 fieldsSet := generic.AddObjectMetaFieldsSet(make(fields.Set, 2), &status.ObjectMeta, true)
129 return pred.MatchesObjectAttributes(
130 status.ObjectMeta.Labels,
131 fieldsSet,
132 )
133 }
134
135 func (rs *REST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
136 servers := rs.GetServersToValidate()
137
138 if server, ok := servers[name]; !ok {
139 return nil, fmt.Errorf("Component not found: %s", name)
140 } else {
141 return rs.getComponentStatus(name, server), nil
142 }
143 }
144
145 func ToConditionStatus(s probe.Result) api.ConditionStatus {
146 switch s {
147 case probe.Success:
148 return api.ConditionTrue
149 case probe.Failure:
150 return api.ConditionFalse
151 default:
152 return api.ConditionUnknown
153 }
154 }
155
156 func (rs *REST) getComponentStatus(name string, server Server) *api.ComponentStatus {
157 status, msg, err := server.DoServerCheck()
158 errorMsg := ""
159 if err != nil {
160 errorMsg = err.Error()
161 }
162
163 c := &api.ComponentCondition{
164 Type: api.ComponentHealthy,
165 Status: ToConditionStatus(status),
166 Message: msg,
167 Error: errorMsg,
168 }
169
170 retVal := &api.ComponentStatus{
171 Conditions: []api.ComponentCondition{*c},
172 }
173 retVal.Name = name
174
175 return retVal
176 }
177
178
179 var _ rest.ShortNamesProvider = &REST{}
180
181
182 func (r *REST) ShortNames() []string {
183 return []string{"cs"}
184 }
185
View as plain text