Skip to content

Commit 81585d0

Browse files
committed
Add generic CombinedStatus type
1 parent 6a02299 commit 81585d0

File tree

1 file changed

+231
-0
lines changed

1 file changed

+231
-0
lines changed

cluster-autoscaler/processors/status/scale_up_status_processor.go

+231
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ limitations under the License.
1717
package status
1818

1919
import (
20+
"fmt"
21+
"sort"
22+
"strings"
23+
2024
apiv1 "k8s.io/api/core/v1"
2125
"k8s.io/autoscaler/cluster-autoscaler/utils/errors"
2226

@@ -143,3 +147,230 @@ func UpdateScaleUpError(s *ScaleUpStatus, err errors.AutoscalerError) (*ScaleUpS
143147
s.Result = ScaleUpError
144148
return s, err
145149
}
150+
151+
152+
type combinedStatusSet struct {
153+
Result ScaleUpResult
154+
ScaleupErrors map[*errors.AutoscalerError]bool
155+
ScaleUpInfosSet map[nodegroupset.ScaleUpInfo]bool
156+
PodsTriggeredScaleUpSet map[*apiv1.Pod]bool
157+
PodsRemainUnschedulableSet map[*NoScaleUpInfo]bool
158+
PodsAwaitEvaluationSet map[*apiv1.Pod]bool
159+
CreateNodeGroupResultsSet map[*nodegroups.CreateNodeGroupResult]bool
160+
ConsideredNodeGroupsSet map[cloudprovider.NodeGroup]bool
161+
FailedCreationNodeGroupsSet map[cloudprovider.NodeGroup]bool
162+
FailedResizeNodeGroupsSet map[cloudprovider.NodeGroup]bool
163+
}
164+
165+
func (c *combinedStatusSet) Add(status *ScaleUpStatus) {
166+
resultPriority := map[ScaleUpResult]int{
167+
ScaleUpNotTried: 0,
168+
ScaleUpNotNeeded: 1,
169+
ScaleUpNoOptionsAvailable: 2,
170+
ScaleUpError: 3,
171+
ScaleUpSuccessful: 4,
172+
}
173+
174+
if resultPriority[c.Result] < resultPriority[status.Result] {
175+
c.Result = status.Result
176+
}
177+
if status.ScaleUpError != nil {
178+
if _, found := c.ScaleupErrors[status.ScaleUpError]; !found {
179+
c.ScaleupErrors[status.ScaleUpError] = true
180+
}
181+
}
182+
if status.ScaleUpInfos != nil {
183+
for _, scaleUpInfo := range status.ScaleUpInfos {
184+
if _, found := c.ScaleUpInfosSet[scaleUpInfo]; !found {
185+
c.ScaleUpInfosSet[scaleUpInfo] = true
186+
}
187+
}
188+
}
189+
if status.PodsTriggeredScaleUp != nil {
190+
for _, pod := range status.PodsTriggeredScaleUp {
191+
if _, found := c.PodsTriggeredScaleUpSet[pod]; !found {
192+
c.PodsTriggeredScaleUpSet[pod] = true
193+
}
194+
}
195+
}
196+
if status.PodsRemainUnschedulable != nil {
197+
for _, pod := range status.PodsRemainUnschedulable {
198+
if _, found := c.PodsRemainUnschedulableSet[&pod]; !found {
199+
c.PodsRemainUnschedulableSet[&pod] = true
200+
}
201+
}
202+
}
203+
if status.PodsAwaitEvaluation != nil {
204+
for _, pod := range status.PodsAwaitEvaluation {
205+
if _, found := c.PodsAwaitEvaluationSet[pod]; !found {
206+
c.PodsAwaitEvaluationSet[pod] = true
207+
}
208+
}
209+
}
210+
if status.CreateNodeGroupResults != nil {
211+
for _, createNodeGroupResult := range status.CreateNodeGroupResults {
212+
if _, found := c.CreateNodeGroupResultsSet[&createNodeGroupResult]; !found {
213+
c.CreateNodeGroupResultsSet[&createNodeGroupResult] = true
214+
}
215+
}
216+
}
217+
if status.ConsideredNodeGroups != nil {
218+
for _, nodeGroup := range status.ConsideredNodeGroups {
219+
if _, found := c.ConsideredNodeGroupsSet[nodeGroup]; !found {
220+
c.ConsideredNodeGroupsSet[nodeGroup] = true
221+
}
222+
}
223+
}
224+
if status.FailedCreationNodeGroups != nil {
225+
for _, nodeGroup := range status.FailedCreationNodeGroups {
226+
if _, found := c.FailedCreationNodeGroupsSet[nodeGroup]; !found {
227+
c.FailedCreationNodeGroupsSet[nodeGroup] = true
228+
}
229+
}
230+
}
231+
if status.FailedResizeNodeGroups != nil {
232+
for _, nodeGroup := range status.FailedResizeNodeGroups {
233+
if _, found := c.FailedResizeNodeGroupsSet[nodeGroup]; !found {
234+
c.FailedResizeNodeGroupsSet[nodeGroup] = true
235+
}
236+
}
237+
}
238+
}
239+
240+
func (c *combinedStatusSet) formatMessageFromBatchErrors(errs []errors.AutoscalerError, printErrorTypes bool) string {
241+
firstErr := errs[0]
242+
var builder strings.Builder
243+
builder.WriteString(firstErr.Error())
244+
builder.WriteString(" ...and other concurrent errors: [")
245+
formattedErrs := map[errors.AutoscalerError]bool{
246+
firstErr: true,
247+
}
248+
for _, err := range errs {
249+
if _, has := formattedErrs[err]; has {
250+
continue
251+
}
252+
formattedErrs[err] = true
253+
var message string
254+
if printErrorTypes {
255+
message = fmt.Sprintf("[%s] %s", err.Type(), err.Error())
256+
} else {
257+
message = err.Error()
258+
}
259+
if len(formattedErrs) > 2 {
260+
builder.WriteString(", ")
261+
}
262+
builder.WriteString(fmt.Sprintf("%q", message))
263+
}
264+
builder.WriteString("]")
265+
return builder.String()
266+
}
267+
268+
func (c *combinedStatusSet) combineBatchScaleUpErrors() *errors.AutoscalerError {
269+
if len(c.ScaleupErrors) == 0 {
270+
return nil
271+
}
272+
if len(c.ScaleupErrors) == 1 {
273+
for err := range c.ScaleupErrors {
274+
return err
275+
}
276+
}
277+
uniqueMessages := make(map[string]bool)
278+
uniqueTypes := make(map[errors.AutoscalerErrorType]bool)
279+
for err := range c.ScaleupErrors {
280+
uniqueTypes[(*err).Type()] = true
281+
uniqueMessages[(*err).Error()] = true
282+
}
283+
if len(uniqueTypes) == 1 && len(uniqueMessages) == 1 {
284+
for err := range c.ScaleupErrors {
285+
return err
286+
}
287+
}
288+
// sort to stabilize the results and easier log aggregation
289+
errs := make([]errors.AutoscalerError, 0, len(c.ScaleupErrors))
290+
for err := range c.ScaleupErrors {
291+
errs = append(errs, *err)
292+
}
293+
sort.Slice(errs, func(i, j int) bool {
294+
errA := errs[i]
295+
errB := errs[j]
296+
if errA.Type() == errB.Type() {
297+
return errs[i].Error() < errs[j].Error()
298+
}
299+
return errA.Type() < errB.Type()
300+
})
301+
firstErr := errs[0]
302+
printErrorTypes := len(uniqueTypes) > 1
303+
message := c.formatMessageFromBatchErrors(errs, printErrorTypes)
304+
combinedErr := errors.NewAutoscalerError(firstErr.Type(), message)
305+
return &combinedErr
306+
}
307+
308+
func (c *combinedStatusSet) Export() (*ScaleUpStatus, errors.AutoscalerError) {
309+
result := &ScaleUpStatus{Result: c.Result}
310+
if len(c.ScaleupErrors) > 0 {
311+
result.ScaleUpError = c.combineBatchScaleUpErrors()
312+
}
313+
if len(c.ScaleUpInfosSet) > 0 {
314+
for scaleUpInfo := range c.ScaleUpInfosSet {
315+
result.ScaleUpInfos = append(result.ScaleUpInfos, scaleUpInfo)
316+
}
317+
}
318+
if len(c.PodsTriggeredScaleUpSet) > 0 {
319+
for pod := range c.PodsTriggeredScaleUpSet {
320+
result.PodsTriggeredScaleUp = append(result.PodsTriggeredScaleUp, pod)
321+
}
322+
}
323+
if len(c.PodsRemainUnschedulableSet) > 0 {
324+
for pod := range c.PodsRemainUnschedulableSet {
325+
result.PodsRemainUnschedulable = append(result.PodsRemainUnschedulable, *pod)
326+
}
327+
}
328+
if len(c.PodsAwaitEvaluationSet) > 0 {
329+
for pod := range c.PodsAwaitEvaluationSet {
330+
result.PodsAwaitEvaluation = append(result.PodsAwaitEvaluation, pod)
331+
}
332+
}
333+
if len(c.CreateNodeGroupResultsSet) > 0 {
334+
for createNodeGroupResult := range c.CreateNodeGroupResultsSet {
335+
result.CreateNodeGroupResults = append(result.CreateNodeGroupResults, *createNodeGroupResult)
336+
}
337+
}
338+
if len(c.ConsideredNodeGroupsSet) > 0 {
339+
for nodeGroup := range c.ConsideredNodeGroupsSet {
340+
result.ConsideredNodeGroups = append(result.ConsideredNodeGroups, nodeGroup)
341+
}
342+
}
343+
if len(c.FailedCreationNodeGroupsSet) > 0 {
344+
for nodeGroup := range c.FailedCreationNodeGroupsSet {
345+
result.FailedCreationNodeGroups = append(result.FailedCreationNodeGroups, nodeGroup)
346+
}
347+
}
348+
if len(c.FailedResizeNodeGroupsSet) > 0 {
349+
for nodeGroup := range c.FailedResizeNodeGroupsSet {
350+
result.FailedResizeNodeGroups = append(result.FailedResizeNodeGroups, nodeGroup)
351+
}
352+
}
353+
354+
var resErr errors.AutoscalerError
355+
356+
if result.Result == ScaleUpError {
357+
resErr = *result.ScaleUpError
358+
}
359+
360+
return result, resErr
361+
}
362+
363+
func NewCombinedStatusSet() combinedStatusSet {
364+
return combinedStatusSet{
365+
Result: ScaleUpNotTried,
366+
ScaleupErrors: make(map[*errors.AutoscalerError]bool),
367+
ScaleUpInfosSet: make(map[nodegroupset.ScaleUpInfo]bool),
368+
PodsTriggeredScaleUpSet: make(map[*apiv1.Pod]bool),
369+
PodsRemainUnschedulableSet: make(map[*NoScaleUpInfo]bool),
370+
PodsAwaitEvaluationSet: make(map[*apiv1.Pod]bool),
371+
CreateNodeGroupResultsSet: make(map[*nodegroups.CreateNodeGroupResult]bool),
372+
ConsideredNodeGroupsSet: make(map[cloudprovider.NodeGroup]bool),
373+
FailedCreationNodeGroupsSet: make(map[cloudprovider.NodeGroup]bool),
374+
FailedResizeNodeGroupsSet: make(map[cloudprovider.NodeGroup]bool),
375+
}
376+
}

0 commit comments

Comments
 (0)