forked from argoproj/argo-rollouts
/
factory.go
134 lines (123 loc) · 3.78 KB
/
factory.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
126
127
128
129
130
131
132
133
134
package analysis
import (
"fmt"
"strconv"
appsv1 "k8s.io/api/apps/v1"
"github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1"
)
// BuildArgumentsForRolloutAnalysisRun builds the arguments for a analysis base created by a rollout
func BuildArgumentsForRolloutAnalysisRun(args []v1alpha1.AnalysisRunArgument, stableRS, newRS *appsv1.ReplicaSet) []v1alpha1.Argument {
arguments := []v1alpha1.Argument{}
for i := range args {
arg := args[i]
value := arg.Value
if arg.ValueFrom != nil {
switch *arg.ValueFrom.PodTemplateHashValue {
case v1alpha1.Latest:
value = newRS.Labels[v1alpha1.DefaultRolloutUniqueLabelKey]
case v1alpha1.Stable:
value = stableRS.Labels[v1alpha1.DefaultRolloutUniqueLabelKey]
}
}
analysisArg := v1alpha1.Argument{
Name: arg.Name,
Value: &value,
}
arguments = append(arguments, analysisArg)
}
return arguments
}
// BackgroundLabels returns a map[string]string of common labels for the background analysis
func BackgroundLabels(podHash, instanceID string) map[string]string {
labels := map[string]string{
v1alpha1.DefaultRolloutUniqueLabelKey: podHash,
v1alpha1.RolloutTypeLabel: v1alpha1.RolloutTypeBackgroundRunLabel,
}
if instanceID != "" {
labels[v1alpha1.LabelKeyControllerInstanceID] = instanceID
}
return labels
}
// StepLabels returns a map[string]string of common labels for analysisruns created from an analysis step
func StepLabels(index int32, podHash, instanceID string) map[string]string {
indexStr := strconv.Itoa(int(index))
labels := map[string]string{
v1alpha1.DefaultRolloutUniqueLabelKey: podHash,
v1alpha1.RolloutTypeLabel: v1alpha1.RolloutTypeStepLabel,
v1alpha1.RolloutCanaryStepIndexLabel: indexStr,
}
if instanceID != "" {
labels[v1alpha1.LabelKeyControllerInstanceID] = instanceID
}
return labels
}
// ValidateMetrics validates an analysis template spec
func ValidateMetrics(metrics []v1alpha1.Metric) error {
if len(metrics) == 0 {
return fmt.Errorf("no metrics specified")
}
duplicateNames := make(map[string]bool)
for i, metric := range metrics {
if _, ok := duplicateNames[metric.Name]; ok {
return fmt.Errorf("metrics[%d]: duplicate name '%s", i, metric.Name)
}
duplicateNames[metric.Name] = true
if err := ValidateMetric(metric); err != nil {
return fmt.Errorf("metrics[%d]: %v", i, err)
}
}
return nil
}
// ValidateMetric validates a single metric spec
func ValidateMetric(metric v1alpha1.Metric) error {
if metric.Count > 0 {
if metric.Count < metric.FailureLimit {
return fmt.Errorf("count must be >= failureLimit")
}
if metric.Count < metric.InconclusiveLimit {
return fmt.Errorf("count must be >= inconclusiveLimit")
}
}
if metric.Count > 1 && metric.Interval == "" {
return fmt.Errorf("interval must be specified when count > 1")
}
if metric.Interval != "" {
if _, err := metric.Interval.Duration(); err != nil {
return fmt.Errorf("invalid interval string: %v", err)
}
}
if metric.InitialDelay != "" {
if _, err := metric.InitialDelay.Duration(); err != nil {
return fmt.Errorf("invalid startDelay string: %v", err)
}
}
if metric.FailureLimit < 0 {
return fmt.Errorf("failureLimit must be >= 0")
}
if metric.InconclusiveLimit < 0 {
return fmt.Errorf("inconclusiveLimit must be >= 0")
}
if metric.ConsecutiveErrorLimit != nil && *metric.ConsecutiveErrorLimit < 0 {
return fmt.Errorf("consecutiveErrorLimit must be >= 0")
}
numProviders := 0
if metric.Provider.Prometheus != nil {
numProviders++
}
if metric.Provider.Job != nil {
numProviders++
}
if metric.Provider.Web != nil {
numProviders++
}
if metric.Provider.Wavefront != nil {
numProviders++
}
if numProviders == 0 {
return fmt.Errorf("no provider specified")
}
if numProviders > 1 {
return fmt.Errorf("multiple providers specified")
}
return nil
}