-
Notifications
You must be signed in to change notification settings - Fork 117
/
redis_experimentation.go
111 lines (93 loc) · 3.5 KB
/
redis_experimentation.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
package redisexperimentation
// <!-- START clutchdoc -->
// description: Chaos Experimentation Framework - Supports Redis specific experiments.
// <!-- END clutchdoc -->
import (
"errors"
"fmt"
"github.com/golang/protobuf/ptypes/any"
"github.com/uber-go/tally/v4"
"go.uber.org/zap"
experimentationv1 "github.com/lyft/clutch/backend/api/chaos/experimentation/v1"
redisexperimentationv1 "github.com/lyft/clutch/backend/api/chaos/redisexperimentation/v1"
configv1 "github.com/lyft/clutch/backend/api/config/module/chaos/redisexperimentation/v1"
"github.com/lyft/clutch/backend/module"
"github.com/lyft/clutch/backend/module/chaos/experimentation/xds"
redisexperimentationxds "github.com/lyft/clutch/backend/module/chaos/redisexperimentation/xds"
"github.com/lyft/clutch/backend/service"
"github.com/lyft/clutch/backend/service/chaos/experimentation/experimentstore"
)
const (
Name = "clutch.module.chaos.redisexperimentation"
)
type Service struct {
storer experimentstore.Storer
}
// New instantiates a Service object.
func New(untypedConfig *any.Any, logger *zap.Logger, scope tally.Scope) (module.Module, error) {
config := &configv1.Config{}
if err := untypedConfig.UnmarshalTo(config); err != nil {
return nil, err
}
store, ok := service.Registry[experimentstore.Name]
if !ok {
return nil, errors.New("could not find experiment store service")
}
storer, ok := store.(experimentstore.Storer)
if !ok {
return nil, errors.New("service was not the correct type")
}
xds.RTDSGeneratorsByTypeUrl[xds.TypeUrl(&redisexperimentationv1.FaultConfig{})] = &redisexperimentationxds.RTDSFaultsGenerator{
FaultRuntimePrefix: config.FaultRuntimePrefix,
}
return &Service{
storer: storer,
}, nil
}
func (s *Service) Register(r module.Registrar) error {
transformation := experimentstore.Transformation{ConfigTypeUrl: "type.googleapis.com/clutch.chaos.redisexperimentation.v1.FaultConfig", RunTransform: s.transform}
return s.storer.RegisterTransformation(transformation)
}
func (s *Service) transform(_ *experimentstore.ExperimentRun, config *experimentstore.ExperimentConfig) ([]*experimentationv1.Property, error) {
var experimentConfig = redisexperimentationv1.FaultConfig{}
if err := config.Config.UnmarshalTo(&experimentConfig); err != nil {
return []*experimentationv1.Property{}, err
}
faultsDescription, err := experimentConfigToFaultString(&experimentConfig)
if err != nil {
return nil, err
}
var downstream, upstream string
downstream = experimentConfig.GetFaultTargeting().GetDownstreamCluster().GetName()
upstream = experimentConfig.GetFaultTargeting().GetUpstreamCluster().GetName()
return []*experimentationv1.Property{
{
Id: "type",
Label: "Type",
Value: &experimentationv1.Property_StringValue{StringValue: "Redis"},
},
{
Id: "target",
Label: "Target",
Value: &experimentationv1.Property_StringValue{StringValue: fmt.Sprintf("%s ➡️ %s", downstream, upstream)},
},
{
Id: "fault_types",
Label: "Fault Types",
Value: &experimentationv1.Property_StringValue{StringValue: faultsDescription},
},
}, nil
}
func experimentConfigToFaultString(experiment *redisexperimentationv1.FaultConfig) (string, error) {
if experiment == nil {
return "", errors.New("experiment is nil")
}
switch experiment.GetFault().(type) {
case *redisexperimentationv1.FaultConfig_ErrorFault:
return "Error", nil
case *redisexperimentationv1.FaultConfig_LatencyFault:
return "Delay", nil
default:
return "", fmt.Errorf("unexpected fault type %v", experiment.GetFault())
}
}