Skip to content

Commit b9fa6e0

Browse files
authored
Merge pull request kubernetes#83680 from bclau/tests/network-large-requests
tests: Adds large requests tests
2 parents 6c5fb3e + 56fe87d commit b9fa6e0

File tree

2 files changed

+57
-14
lines changed

2 files changed

+57
-14
lines changed

test/e2e/framework/network/utils.go

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ const (
7373
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})))?::))))"
7474
resizeNodeReadyTimeout = 2 * time.Minute
7575
resizeNodeNotReadyTimeout = 2 * time.Minute
76+
// netexec dial commands
77+
// the destination will echo its hostname.
78+
echoHostname = "hostname"
7679
)
7780

7881
// NetexecImageName is the image name for agnhost.
@@ -146,12 +149,30 @@ type NetworkingTestConfig struct {
146149

147150
// DialFromEndpointContainer executes a curl via kubectl exec in an endpoint container.
148151
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)
150153
}
151154

152155
// DialFromTestContainer executes a curl via kubectl exec in a test container.
153156
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)
155176
}
156177

157178
// diagnoseMissingEndpoints prints debug information about the endpoints that
@@ -186,23 +207,29 @@ func (config *NetworkingTestConfig) EndpointHostnames() sets.String {
186207
// at least once.
187208
// - maxTries is the maximum number of curl attempts. If this many attempts pass
188209
// 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.
191217
// maxTries == minTries will confirm that we see the expected endpoints and no
192218
// more for maxTries. Use this if you want to eg: fail a readiness check on a
193219
// 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) {
195221
ipPort := net.JoinHostPort(containerIP, strconv.Itoa(containerHTTPPort))
196222
// The current versions of curl included in CentOS and RHEL distros
197223
// misinterpret square brackets around IPv6 as globbing, so use the -g
198224
// 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'",
200226
ipPort,
227+
dialCommand,
201228
protocol,
202229
targetIP,
203230
targetPort)
204231

205-
eps := sets.NewString()
232+
responses := sets.NewString()
206233

207234
for i := 0; i < maxTries; i++ {
208235
stdout, stderr, err := config.f.ExecShellInPodWithFullOutput(config.HostTestContainerPod.Name, cmd)
@@ -219,25 +246,27 @@ func (config *NetworkingTestConfig) DialFromContainer(protocol, containerIP, tar
219246
continue
220247
}
221248

222-
for _, hostName := range output["responses"] {
223-
trimmed := strings.TrimSpace(hostName)
249+
for _, response := range output["responses"] {
250+
trimmed := strings.TrimSpace(response)
224251
if trimmed != "" {
225-
eps.Insert(trimmed)
252+
responses.Insert(trimmed)
226253
}
227254
}
228255
}
229-
framework.Logf("Waiting for endpoints: %v", expectedEps.Difference(eps))
256+
framework.Logf("Waiting for responses: %v", expectedResponses.Difference(responses))
230257

231258
// 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 {
233260
return
234261
}
235262
// TODO: get rid of this delay #36281
236263
time.Sleep(hitEndpointRetryDelay)
237264
}
238265

239-
config.diagnoseMissingEndpoints(eps)
240-
framework.Failf("Failed to find expected endpoints:\nTries %d\nCommand %v\nretrieved %v\nexpected %v\n", maxTries, cmd, eps, expectedEps)
266+
if dialCommand == echoHostname {
267+
config.diagnoseMissingEndpoints(responses)
268+
}
269+
framework.Failf("Failed to find expected responses:\nTries %d\nCommand %v\nretrieved %v\nexpected %v\n", maxTries, cmd, responses, expectedResponses)
241270
}
242271

243272
// GetEndpointsFromTestContainer executes a curl via kubectl exec in a test container.

test/e2e/network/networking.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,20 @@ var _ = SIGDescribe("Networking", func() {
295295
framework.Failf("Unexpected endpoints return: %v, expect 1 endpoints", eps)
296296
}
297297
})
298+
299+
ginkgo.It("should be able to handle large requests: http", func() {
300+
config := e2enetwork.NewNetworkingTestConfig(f)
301+
ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
302+
message := strings.Repeat("42", 1000)
303+
config.DialEchoFromTestContainer("http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, message)
304+
})
305+
306+
ginkgo.It("should be able to handle large requests: udp", func() {
307+
config := e2enetwork.NewNetworkingTestConfig(f)
308+
ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
309+
message := "n" + strings.Repeat("o", 1999)
310+
config.DialEchoFromTestContainer("udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, message)
311+
})
298312
})
299313

300314
ginkgo.It("should recreate its iptables rules if they are deleted [Disruptive]", func() {

0 commit comments

Comments
 (0)