...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package generic
17
18 import (
19 "crypto/rand"
20 "math"
21 "math/big"
22 "strconv"
23
24 "github.com/pkg/errors"
25
26 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
27 )
28
29
30 func FilterObjectsByMode(mode v1alpha1.SelectorMode, value string, count int) ([]uint, error) {
31 if count == 0 {
32 return nil, errors.New("cannot generate objects from empty list")
33 }
34
35 switch mode {
36 case v1alpha1.OneMode:
37 index := getRandomNumber(count)
38 return []uint{uint(index)}, nil
39 case v1alpha1.AllMode:
40 return RandomFixedIndexes(0, uint(count), uint(count)+1), nil
41 case v1alpha1.FixedMode:
42 num, err := strconv.Atoi(value)
43 if err != nil {
44 return nil, err
45 }
46
47 if count < num {
48 num = count
49 }
50
51 if num <= 0 {
52 return nil, errors.New("cannot select any object as value below or equal 0")
53 }
54
55 return RandomFixedIndexes(0, uint(count), uint(num)), nil
56 case v1alpha1.FixedPercentMode:
57 percentage, err := strconv.Atoi(value)
58 if err != nil {
59 return nil, err
60 }
61
62 if percentage == 0 {
63 return nil, errors.New("cannot select any object as value below or equal 0")
64 }
65
66 if percentage < 0 || percentage > 100 {
67 return nil, errors.Errorf("fixed percentage value of %d is invalid, Must be (0,100]", percentage)
68 }
69
70
71 num := int(math.Ceil(float64(count) * float64(percentage) / 100))
72
73 return RandomFixedIndexes(0, uint(count), uint(num)), nil
74 case v1alpha1.RandomMaxPercentMode:
75 maxPercentage, err := strconv.Atoi(value)
76 if err != nil {
77 return nil, err
78 }
79
80 if maxPercentage == 0 {
81 return nil, errors.New("cannot select any object as value below or equal 0")
82 }
83
84 if maxPercentage < 0 || maxPercentage > 100 {
85 return nil, errors.Errorf("fixed percentage value of %d is invalid, Must be [0-100]", maxPercentage)
86 }
87
88 percentage := getRandomNumber(maxPercentage + 1)
89 num := int(math.Ceil(float64(count) * float64(percentage) / 100))
90
91 return RandomFixedIndexes(0, uint(count), uint(num)), nil
92 default:
93 return nil, errors.Errorf("mode %s not supported", mode)
94 }
95 }
96
97
98
99 func RandomFixedIndexes(start, end, count uint) []uint {
100 var indexes []uint
101 m := make(map[uint]uint, count)
102
103 if end < start {
104 return indexes
105 }
106
107 if count > end-start {
108 for i := start; i < end; i++ {
109 indexes = append(indexes, i)
110 }
111
112 return indexes
113 }
114
115 for i := 0; i < int(count); {
116 index := uint(getRandomNumber(int(end-start))) + start
117
118 _, exist := m[index]
119 if exist {
120 continue
121 }
122
123 m[index] = index
124 indexes = append(indexes, index)
125 i++
126 }
127
128 return indexes
129 }
130
131 func getRandomNumber(max int) uint64 {
132 num, _ := rand.Int(rand.Reader, big.NewInt(int64(max)))
133 return num.Uint64()
134 }
135