@@ -73,6 +73,9 @@ const (
73
73
RegexIPv6 = "(?:(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\ .){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-fA-F]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\ .){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\ .){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,1}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\ .){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,2}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\ .){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,3}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:[0-9a-fA-F]{1,4})):)(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\ .){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,4}(?:(?:[0-9a-fA-F]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\ .){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,5}(?:(?:[0-9a-fA-F]{1,4})))?::)(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,6}(?:(?:[0-9a-fA-F]{1,4})))?::))))"
74
74
resizeNodeReadyTimeout = 2 * time .Minute
75
75
resizeNodeNotReadyTimeout = 2 * time .Minute
76
+ // netexec dial commands
77
+ // the destination will echo its hostname.
78
+ echoHostname = "hostname"
76
79
)
77
80
78
81
// NetexecImageName is the image name for agnhost.
@@ -146,12 +149,30 @@ type NetworkingTestConfig struct {
146
149
147
150
// DialFromEndpointContainer executes a curl via kubectl exec in an endpoint container.
148
151
func (config * NetworkingTestConfig ) DialFromEndpointContainer (protocol , targetIP string , targetPort , maxTries , minTries int , expectedEps sets.String ) {
149
- config .DialFromContainer (protocol , config .EndpointPods [0 ].Status .PodIP , targetIP , EndpointHTTPPort , targetPort , maxTries , minTries , expectedEps )
152
+ config .DialFromContainer (protocol , echoHostname , config .EndpointPods [0 ].Status .PodIP , targetIP , EndpointHTTPPort , targetPort , maxTries , minTries , expectedEps )
150
153
}
151
154
152
155
// DialFromTestContainer executes a curl via kubectl exec in a test container.
153
156
func (config * NetworkingTestConfig ) DialFromTestContainer (protocol , targetIP string , targetPort , maxTries , minTries int , expectedEps sets.String ) {
154
- config .DialFromContainer (protocol , config .TestContainerPod .Status .PodIP , targetIP , testContainerHTTPPort , targetPort , maxTries , minTries , expectedEps )
157
+ config .DialFromContainer (protocol , echoHostname , config .TestContainerPod .Status .PodIP , targetIP , testContainerHTTPPort , targetPort , maxTries , minTries , expectedEps )
158
+ }
159
+
160
+ // DialEchoFromTestContainer executes a curl via kubectl exec in a test container. The response is expected to match the echoMessage.
161
+ func (config * NetworkingTestConfig ) DialEchoFromTestContainer (protocol , targetIP string , targetPort , maxTries , minTries int , echoMessage string ) {
162
+ expectedResponse := sets .NewString ()
163
+ expectedResponse .Insert (echoMessage )
164
+ var dialCommand string
165
+
166
+ // NOTE(claudiub): netexec /dialCommand will send a request to the given targetIP and targetPort as follows:
167
+ // for HTTP: it will send a request to: http://targetIP:targetPort/dialCommand
168
+ // for UDP: it will send targetCommand as a message. The consumer receives the data message and looks for
169
+ // a few starting strings, including echo, and treats it accordingly.
170
+ if protocol == "http" {
171
+ dialCommand = fmt .Sprintf ("echo?msg=%s" , echoMessage )
172
+ } else {
173
+ dialCommand = fmt .Sprintf ("echo%%20%s" , echoMessage )
174
+ }
175
+ config .DialFromContainer (protocol , dialCommand , config .TestContainerPod .Status .PodIP , targetIP , testContainerHTTPPort , targetPort , maxTries , minTries , expectedResponse )
155
176
}
156
177
157
178
// diagnoseMissingEndpoints prints debug information about the endpoints that
@@ -186,23 +207,29 @@ func (config *NetworkingTestConfig) EndpointHostnames() sets.String {
186
207
// at least once.
187
208
// - maxTries is the maximum number of curl attempts. If this many attempts pass
188
209
// and we don't see all expected endpoints, the test fails.
189
- // - expectedEps is the set of endpointnames to wait for. Typically this is also
190
- // the hostname reported by each pod in the service through /hostName.
210
+ // - targetIP is the source Pod IP that will dial the given dialCommand using the given protocol.
211
+ // - dialCommand is the command that the targetIP will send to the targetIP using the given protocol.
212
+ // the dialCommand should be formatted properly for the protocol (http: URL path+parameters,
213
+ // udp: command%20parameters, where parameters are optional)
214
+ // - expectedResponses is the unordered set of responses to wait for. The responses are based on
215
+ // the dialCommand; for example, for the dialCommand "hostname", the expectedResponses
216
+ // should contain the hostnames reported by each pod in the service through /hostName.
191
217
// maxTries == minTries will confirm that we see the expected endpoints and no
192
218
// more for maxTries. Use this if you want to eg: fail a readiness check on a
193
219
// pod and confirm it doesn't show up as an endpoint.
194
- func (config * NetworkingTestConfig ) DialFromContainer (protocol , containerIP , targetIP string , containerHTTPPort , targetPort , maxTries , minTries int , expectedEps sets.String ) {
220
+ func (config * NetworkingTestConfig ) DialFromContainer (protocol , dialCommand , containerIP , targetIP string , containerHTTPPort , targetPort , maxTries , minTries int , expectedResponses sets.String ) {
195
221
ipPort := net .JoinHostPort (containerIP , strconv .Itoa (containerHTTPPort ))
196
222
// The current versions of curl included in CentOS and RHEL distros
197
223
// misinterpret square brackets around IPv6 as globbing, so use the -g
198
224
// argument to disable globbing to handle the IPv6 case.
199
- cmd := fmt .Sprintf ("curl -g -q -s 'http://%s/dial?request=hostName &protocol=%s&host=%s&port=%d&tries=1'" ,
225
+ cmd := fmt .Sprintf ("curl -g -q -s 'http://%s/dial?request=%s &protocol=%s&host=%s&port=%d&tries=1'" ,
200
226
ipPort ,
227
+ dialCommand ,
201
228
protocol ,
202
229
targetIP ,
203
230
targetPort )
204
231
205
- eps := sets .NewString ()
232
+ responses := sets .NewString ()
206
233
207
234
for i := 0 ; i < maxTries ; i ++ {
208
235
stdout , stderr , err := config .f .ExecShellInPodWithFullOutput (config .HostTestContainerPod .Name , cmd )
@@ -219,25 +246,27 @@ func (config *NetworkingTestConfig) DialFromContainer(protocol, containerIP, tar
219
246
continue
220
247
}
221
248
222
- for _ , hostName := range output ["responses" ] {
223
- trimmed := strings .TrimSpace (hostName )
249
+ for _ , response := range output ["responses" ] {
250
+ trimmed := strings .TrimSpace (response )
224
251
if trimmed != "" {
225
- eps .Insert (trimmed )
252
+ responses .Insert (trimmed )
226
253
}
227
254
}
228
255
}
229
- framework .Logf ("Waiting for endpoints : %v" , expectedEps .Difference (eps ))
256
+ framework .Logf ("Waiting for responses : %v" , expectedResponses .Difference (responses ))
230
257
231
258
// Check against i+1 so we exit if minTries == maxTries.
232
- if (eps .Equal (expectedEps ) || eps .Len () == 0 && expectedEps .Len () == 0 ) && i + 1 >= minTries {
259
+ if (responses .Equal (expectedResponses ) || responses .Len () == 0 && expectedResponses .Len () == 0 ) && i + 1 >= minTries {
233
260
return
234
261
}
235
262
// TODO: get rid of this delay #36281
236
263
time .Sleep (hitEndpointRetryDelay )
237
264
}
238
265
239
- config .diagnoseMissingEndpoints (eps )
240
- framework .Failf ("Failed to find expected endpoints:\n Tries %d\n Command %v\n retrieved %v\n expected %v\n " , maxTries , cmd , eps , expectedEps )
266
+ if dialCommand == echoHostname {
267
+ config .diagnoseMissingEndpoints (responses )
268
+ }
269
+ framework .Failf ("Failed to find expected responses:\n Tries %d\n Command %v\n retrieved %v\n expected %v\n " , maxTries , cmd , responses , expectedResponses )
241
270
}
242
271
243
272
// GetEndpointsFromTestContainer executes a curl via kubectl exec in a test container.
0 commit comments