forked from joeholley/supergloo
/
retries.go
126 lines (119 loc) · 3.96 KB
/
retries.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
package apply
import (
"context"
"strings"
"time"
"github.com/solo-io/supergloo/cli/pkg/constants"
"github.com/gogo/protobuf/types"
"github.com/solo-io/supergloo/pkg/api/external/istio/networking/v1alpha3"
"github.com/spf13/pflag"
"github.com/solo-io/go-utils/errors"
"github.com/solo-io/supergloo/cli/pkg/flagutils"
"github.com/solo-io/supergloo/cli/pkg/options"
"github.com/solo-io/supergloo/cli/pkg/surveyutils"
v1 "github.com/solo-io/supergloo/pkg/api/v1"
)
var retryCommand = routingRuleSpecCommand{
use: "retries",
alias: "rt",
short: "apply a retry rule",
long: `Retry rules are used to retry failed requests within a Mesh.
The retries command contains subcommands for different types of retry policies.
The retry policy you choose may only be compatible with a certain mesh type.
See documentation at https://supergloo.solo.io for more information.`,
subCmds: retrySubCommands,
}
func isValidRetryOnValue(valueList string) bool {
vals := strings.Split(valueList, ",")
for _, val := range vals {
var valid bool
for _, possible := range constants.PossibleMaxRetry_RetryOnValues {
if val == possible {
valid = true
break
}
}
if !valid {
return false
}
}
return true
}
var retrySubCommands = []routingRuleSpecCommand{
{
use: "max",
alias: "m",
short: "apply a max retry policy rule. currently only used by managed Istio meshes",
addFlagsFunc: func(set *pflag.FlagSet, in *options.RoutingRuleSpec) {
flagutils.AddMaxRetriesFlags(set, &in.Retries.MaxRetries)
},
specSurveyFunc: func(ctx context.Context, in *options.CreateRoutingRule) error {
return surveyutils.SurveyMaxRetries(&in.RoutingRuleSpec.Retries.MaxRetries)
},
convertSpecFunc: func(in options.RoutingRuleSpec) (*v1.RoutingRuleSpec, error) {
if in.Retries.MaxRetries.Attempts == 0 {
return nil, errors.Errorf("attempts cannot be 0")
}
if in.Retries.MaxRetries.PerTryTimeout < time.Second {
return nil, errors.Errorf("per try timeout must be >=1s")
}
if !isValidRetryOnValue(in.Retries.MaxRetries.RetryOn) {
return nil, errors.Errorf("invalid value for ")
}
return &v1.RoutingRuleSpec{
RuleType: &v1.RoutingRuleSpec_Retries{
Retries: &v1.RetryPolicy{
MaxRetries: &v1alpha3.HTTPRetry{
Attempts: int32(in.Retries.MaxRetries.Attempts),
PerTryTimeout: types.DurationProto(in.Retries.MaxRetries.PerTryTimeout),
RetryOn: in.Retries.MaxRetries.RetryOn,
},
},
},
}, nil
},
updateExistingFunc: func(old, new *v1.RoutingRuleSpec) {
oldRetryPolicy := old.GetRetries()
if oldRetryPolicy == nil {
return
}
// preserve retry budget
new.GetRetries().RetryBudget = oldRetryPolicy.RetryBudget
},
},
{
use: "budget",
alias: "b",
short: "apply a retry budget policy. currently only used by managed Linkerd meshes",
addFlagsFunc: func(set *pflag.FlagSet, in *options.RoutingRuleSpec) {
flagutils.AddRetryBudgetFlags(set, &in.Retries.RetryBudget)
},
specSurveyFunc: func(ctx context.Context, in *options.CreateRoutingRule) error {
return surveyutils.SurveyRetryBudget(&in.RoutingRuleSpec.Retries.RetryBudget)
},
convertSpecFunc: func(in options.RoutingRuleSpec) (*v1.RoutingRuleSpec, error) {
if in.Retries.RetryBudget.RetryRatio < 0 || in.Retries.RetryBudget.RetryRatio > 1 {
return nil, errors.Errorf("retry ratio must be a percentage between 0 and 1")
}
return &v1.RoutingRuleSpec{
RuleType: &v1.RoutingRuleSpec_Retries{
Retries: &v1.RetryPolicy{
RetryBudget: &v1.RetryBudget{
RetryRatio: in.Retries.RetryBudget.RetryRatio,
MinRetriesPerSecond: in.Retries.RetryBudget.MinRetriesPerSecond,
Ttl: in.Retries.RetryBudget.Ttl,
},
},
},
}, nil
},
updateExistingFunc: func(old, new *v1.RoutingRuleSpec) {
oldRetryPolicy := old.GetRetries()
if oldRetryPolicy == nil {
return
}
// preserve max retries
new.GetRetries().MaxRetries = oldRetryPolicy.MaxRetries
},
},
}