-
Notifications
You must be signed in to change notification settings - Fork 115
/
promotions.go
125 lines (108 loc) · 3.09 KB
/
promotions.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package garbage
import (
"context"
"fmt"
"sort"
"time"
"sigs.k8s.io/controller-runtime/pkg/client"
kargoapi "github.com/akuity/kargo/api/v1alpha1"
"github.com/akuity/kargo/internal/kubeclient"
"github.com/akuity/kargo/internal/logging"
)
// cleanProjectPromotions steps through all Stages in the specified Project and,
// for each, deletes all Promotions meeting the following criteria:
// - More than some configurable number of generations older than the oldest
// Promotion (from the same Stage) in a non-terminal phase.
// - Older than some configurable minimum age.
func (c *collector) cleanProjectPromotions(ctx context.Context, project string) error {
logger := logging.LoggerFromContext(ctx).WithValues("project", project)
stages := &kargoapi.StageList{}
if err := c.listStagesFn(
ctx,
stages,
client.InNamespace(project),
); err != nil {
return fmt.Errorf("error listing Stages in Project %q: %w", project, err)
}
var cleanErrCount int
for _, stage := range stages.Items {
stageLogger := logger.WithValues("stage", stage.Name)
if err := c.cleanStagePromotionsFn(ctx, project, stage.Name); err != nil {
stageLogger.Error(err, "error cleaning Promotions to Stage")
cleanErrCount++
continue
}
stageLogger.Debug("cleaned Promotions to Stage")
}
if cleanErrCount > 0 {
return fmt.Errorf(
"error cleaning Promotions to one or more Stages in Project %q",
project,
)
}
return nil
}
func (c *collector) cleanStagePromotions(
ctx context.Context,
project string,
stage string,
) error {
logger := logging.LoggerFromContext(ctx).WithValues(
"project", project,
"stage", stage,
)
promos := kargoapi.PromotionList{}
if err := c.listPromotionsFn(
ctx,
&promos,
client.InNamespace(project),
client.MatchingFields{
kubeclient.PromotionsByStageIndexField: stage,
},
); err != nil {
return fmt.Errorf(
"error listing Promotions to Stage %q in Project %q: %w",
stage,
project,
err,
)
}
if len(promos.Items) <= c.cfg.MaxRetainedPromotions {
return nil // Done
}
// Sort Promotions by creation time
sort.Sort(promosByCreation(promos.Items))
// Step through all Promotions to find the oldest that is not terminal
oldestNonTerminalIndex := -1
for i, promo := range promos.Items {
if !promo.Status.Phase.IsTerminal() {
oldestNonTerminalIndex = i
}
}
firstToDeleteIndex := oldestNonTerminalIndex + c.cfg.MaxRetainedPromotions + 1
if firstToDeleteIndex >= len(promos.Items) {
return nil // Done
}
var deleteErrCount int
for i := firstToDeleteIndex; i < len(promos.Items); i++ {
promo := promos.Items[i]
if time.Since(promo.CreationTimestamp.Time) < c.cfg.MinPromotionDeletionAge {
continue // Not old enough
}
promoLogger := logger.WithValues("promotion", promo.Name)
if err := c.deletePromotionFn(ctx, &promo); err != nil {
promoLogger.Error(err, "error deleting Promotion")
deleteErrCount++
} else {
promoLogger.Debug("deleted Promotion")
}
}
if deleteErrCount > 0 {
return fmt.Errorf(
"error deleting one or more Promotions from Stage %q in Project %q",
stage,
project,
)
}
return nil
}