@@ -17,11 +17,14 @@ limitations under the License.
17
17
package e2e
18
18
19
19
import (
20
+ "bufio"
21
+ "bytes"
20
22
"context"
21
23
"fmt"
24
+ "io"
25
+ "os"
22
26
"os/exec"
23
27
"strconv"
24
- "strings"
25
28
"testing"
26
29
"time"
27
30
@@ -30,88 +33,117 @@ import (
30
33
)
31
34
32
35
func waitResource (ctx context.Context , t * testing.T , kwokctlPath , name , resource , reason string , want , gap , tolerance int ) error {
33
- var prev int
36
+ cmd := exec .CommandContext (ctx , kwokctlPath , "--name" , name , "kubectl" , "get" , "--no-headers" , "--watch" , resource )
37
+ cmd .Stderr = os .Stderr
38
+ pr , err := cmd .StdoutPipe ()
39
+ if err != nil {
40
+ return err
41
+ }
42
+
43
+ err = cmd .Start ()
44
+ if err != nil {
45
+ return err
46
+ }
47
+
48
+ uniq := map [string ]int {}
49
+ prev := 0
50
+ got := 0
51
+ var latestTime time.Time
52
+ reader := bufio .NewReader (io .TeeReader (pr , os .Stderr ))
34
53
for {
35
- if ctx .Err () != nil {
36
- return ctx .Err ()
37
- }
38
- cmd := exec .Command (kwokctlPath , "--name" , name , "kubectl" , "get" , "--no-headers" , resource ) // #nosec G204
39
- output , err := cmd .Output ()
54
+ line , _ , err := reader .ReadLine ()
40
55
if err != nil {
56
+ if err != io .EOF {
57
+ return err
58
+ }
59
+
60
+ t .Logf ("%s %d => %d, %v\n " , resource , got , want , latestTime )
41
61
return err
42
62
}
43
- raw := string (output )
44
- got := strings .Count (raw , reason )
63
+
64
+ key := string (line [:bytes .IndexByte (line , byte (' ' ))])
65
+
66
+ _ , ok := uniq [key ]
67
+ if ! ok {
68
+ uniq [key ] = 0
69
+ }
70
+
71
+ if uniq [key ] == 0 {
72
+ if bytes .Contains (line , []byte (reason )) {
73
+ uniq [key ] = 1
74
+ got ++
75
+ }
76
+ }
77
+
45
78
if got == want {
79
+ t .Logf ("%s %d, %v\n " , resource , got , latestTime )
46
80
return nil
47
81
}
48
- all := strings .Count (raw , "\n " )
49
- t .Logf ("%s %d/%d => %d, %v\n " , resource , got , all , want , time .Now ())
82
+
83
+ if time .Since (latestTime ) < time .Second {
84
+ continue
85
+ }
86
+
87
+ latestTime = time .Now ()
88
+
89
+ all := len (uniq )
90
+
91
+ t .Logf ("%s %d/%d => %d, %v\n " , resource , got , all , want , latestTime )
50
92
if prev != 0 && got == prev {
51
93
return fmt .Errorf ("resource %s not changed" , resource )
52
94
}
53
95
prev = got
54
96
if gap != 0 && got != 0 && (all - got ) > gap {
55
- if tolerance > 0 {
56
- t .Logf ("Error %s gap too large, actual: %d, expected: %d, retrying...\n " , resource , all - got , gap )
57
- tolerance --
58
- } else {
59
- t .Logf ("Error %s gap too large, actual: %d, expected: %d\n " , resource , all - got , gap )
60
- return fmt .Errorf ("gap too large for resource %s" , resource )
61
- }
97
+ // if tolerance > 0 {
98
+ t .Logf ("Error %s gap too large, actual: %d, expected: %d, retrying...\n " , resource , all - got , gap )
99
+ // tolerance--
100
+ // } else {
101
+ // t.Logf("Error %s gap too large, actual: %d, expected: %d\n", resource, all-got, gap)
102
+ // return fmt.Errorf("gap too large for resource %s", resource)
103
+ // }
62
104
}
63
- time .Sleep (1 * time .Second )
64
105
}
65
106
}
66
107
67
108
func scaleCreatePod (ctx context.Context , t * testing.T , kwokctlPath string , name string , size int ) error {
68
- cmd := exec .CommandContext (ctx , kwokctlPath , "--name" , name , "kubectl" , "get" , "node" , "-o" , "jsonpath={.items.*.metadata.name}" ) // #nosec G204
69
- out , err := cmd .Output ()
70
- if err != nil {
71
- return fmt .Errorf ("failed to run command: %w" , err )
72
- }
73
- nodeName := ""
74
- nodes := strings .Split (string (out ), " " )
75
- for _ , node := range nodes {
76
- if strings .Contains (node , "fake-" ) {
77
- nodeName = node
78
- break
79
- }
80
- }
81
- if nodeName == "" {
82
- return fmt .Errorf ("no fake- node found" )
83
- }
84
-
109
+ nodeName := "fake-node-000000"
85
110
scaleCmd := exec .CommandContext (ctx , kwokctlPath , "--name" , name , "scale" , "pod" , "fake-pod" , "--replicas" , strconv .Itoa (size ), "--param" , fmt .Sprintf (".nodeName=%q" , nodeName )) // #nosec G204
111
+ scaleCmd .Stdout = os .Stderr
112
+ scaleCmd .Stderr = os .Stderr
86
113
if err := scaleCmd .Start (); err != nil {
87
114
return fmt .Errorf ("failed to start scale command: %w" , err )
88
115
}
89
116
90
- if err := waitResource (ctx , t , kwokctlPath , name , "Pod" , "Running" , size , 5 , 20 ); err != nil {
117
+ if err := waitResource (ctx , t , kwokctlPath , name , "Pod" , "Running" , size , 5 , 10 ); err != nil {
91
118
return fmt .Errorf ("failed to wait for resource: %w" , err )
92
119
}
120
+
93
121
return nil
94
122
}
95
123
96
- func scaleDeletePod (ctx context.Context , t * testing.T , kwokctlPath string , name string , _ int ) error {
124
+ func scaleDeletePod (ctx context.Context , t * testing.T , kwokctlPath string , name string , size int ) error {
97
125
scaleCmd := exec .CommandContext (ctx , kwokctlPath , "--name" , name , "scale" , "pod" , "fake-pod" , "--replicas" , strconv .Itoa (0 )) // #nosec G204
126
+ scaleCmd .Stdout = os .Stderr
127
+ scaleCmd .Stderr = os .Stderr
98
128
if err := scaleCmd .Start (); err != nil {
99
129
return fmt .Errorf ("failed to start scale command: %w" , err )
100
130
}
101
131
102
- if err := waitResource (ctx , t , kwokctlPath , name , "Pod" , "fake-pod- " , 0 , 0 , 0 ); err != nil {
132
+ if err := waitResource (ctx , t , kwokctlPath , name , "Pod" , "Terminating " , size , 0 , 0 ); err != nil {
103
133
return fmt .Errorf ("failed to wait for resource: %w" , err )
104
134
}
105
135
return nil
106
136
}
107
137
108
138
func scaleCreateNode (ctx context.Context , t * testing.T , kwokctlPath string , name string , size int ) error {
109
139
scaleCmd := exec .CommandContext (ctx , kwokctlPath , "--name" , name , "scale" , "node" , "fake-node" , "--replicas" , strconv .Itoa (size )) // #nosec G204
140
+ scaleCmd .Stdout = os .Stderr
141
+ scaleCmd .Stderr = os .Stderr
110
142
if err := scaleCmd .Start (); err != nil {
111
143
return fmt .Errorf ("failed to start scale command: %w" , err )
112
144
}
113
145
114
- if err := waitResource (ctx , t , kwokctlPath , name , "Node" , "Ready" , size , 10 , 20 ); err != nil {
146
+ if err := waitResource (ctx , t , kwokctlPath , name , "Node" , "Ready" , size , 10 , 100 ); err != nil {
115
147
return fmt .Errorf ("failed to wait for resource: %w" , err )
116
148
}
117
149
return nil
@@ -123,17 +155,18 @@ func CaseBenchmark(kwokctlPath, clusterName string) *features.FeatureBuilder {
123
155
ctx0 , cancel := context .WithTimeout (ctx , 240 * time .Second )
124
156
defer cancel ()
125
157
126
- err := scaleCreateNode (ctx0 , t , kwokctlPath , clusterName , 10000 )
158
+ err := scaleCreateNode (ctx0 , t , kwokctlPath , clusterName , 5000 )
127
159
if err != nil {
128
160
t .Fatal (err )
129
161
}
162
+
130
163
return ctx
131
164
}).
132
165
Assess ("Create pods" , func (ctx context.Context , t * testing.T , c * envconf.Config ) context.Context {
133
166
ctx0 , cancel := context .WithTimeout (ctx , 480 * time .Second )
134
167
defer cancel ()
135
168
136
- err := scaleCreatePod (ctx0 , t , kwokctlPath , clusterName , 50000 )
169
+ err := scaleCreatePod (ctx0 , t , kwokctlPath , clusterName , 10000 )
137
170
if err != nil {
138
171
t .Fatal (err )
139
172
}
@@ -143,7 +176,7 @@ func CaseBenchmark(kwokctlPath, clusterName string) *features.FeatureBuilder {
143
176
ctx0 , cancel := context .WithTimeout (ctx , 480 * time .Second )
144
177
defer cancel ()
145
178
146
- err := scaleDeletePod (ctx0 , t , kwokctlPath , clusterName , 50000 )
179
+ err := scaleDeletePod (ctx0 , t , kwokctlPath , clusterName , 10000 )
147
180
if err != nil {
148
181
t .Fatal (err )
149
182
}
0 commit comments