Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix possible flake while testing service endpoints via proxy #98345

Merged
merged 1 commit into from Feb 3, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
125 changes: 69 additions & 56 deletions test/e2e/network/proxy.go
Expand Up @@ -58,6 +58,9 @@ const (
proxyHTTPCallTimeout = 30 * time.Second
podRetryPeriod = 1 * time.Second
podRetryTimeout = 1 * time.Minute

requestRetryPeriod = 10 * time.Millisecond
requestRetryTimeout = 1 * time.Minute
)

type jsonResponse struct {
Expand Down Expand Up @@ -274,6 +277,8 @@ var _ = SIGDescribe("Proxy", func() {

ns := f.Namespace.Name
msg := "foo"
testSvcName := "test-service"
testSvcLabels := map[string]string{"test": "response"}

framework.Logf("Creating pod...")
_, err := f.ClientSet.CoreV1().Pods(ns).Create(context.TODO(), &v1.Pod{
Expand Down Expand Up @@ -302,11 +307,9 @@ var _ = SIGDescribe("Proxy", func() {
framework.Logf("Creating service...")
_, err = f.ClientSet.CoreV1().Services(ns).Create(context.TODO(), &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test-service",
Name: testSvcName,
Namespace: ns,
Labels: map[string]string{
"test": "response",
},
Labels: testSvcLabels,
},
Spec: v1.ServiceSpec{
Ports: []v1.ServicePort{{
Expand Down Expand Up @@ -339,32 +342,9 @@ var _ = SIGDescribe("Proxy", func() {

urlString := f.ClientConfig().Host + "/api/v1/namespaces/" + ns + "/pods/agnhost/proxy/some/path/with/" + httpVerb
framework.Logf("Starting http.Client for %s", urlString)
request, err := http.NewRequest(httpVerb, urlString, nil)
framework.ExpectNoError(err, "processing request")

resp, err := client.Do(request)
framework.ExpectNoError(err, "processing response")
defer resp.Body.Close()

buf := new(bytes.Buffer)
buf.ReadFrom(resp.Body)
response := buf.String()

switch httpVerb {
case "HEAD":
framework.Logf("http.Client request:%s | StatusCode:%d", httpVerb, resp.StatusCode)
framework.ExpectEqual(resp.StatusCode, 200, "The resp.StatusCode returned: %d", resp.StatusCode)
default:
var jr *jsonResponse
err = json.Unmarshal([]byte(response), &jr)
framework.ExpectNoError(err, "Failed to process jsonResponse: %v | err: %v ", buf.String(), err)

framework.Logf("http.Client request:%s | StatusCode:%d | Response: %s | Method: %s", httpVerb, resp.StatusCode, jr.Body, jr.Method)
framework.ExpectEqual(resp.StatusCode, 200, "The resp.StatusCode returned: %d", resp.StatusCode)

framework.ExpectEqual(msg, jr.Body, "The resp.Body returned: %v", jr.Body)
framework.ExpectEqual(httpVerb, jr.Method, "The resp.Body returned: %v", jr.Body)
}

pollErr := wait.PollImmediate(requestRetryPeriod, requestRetryTimeout, validateProxyVerbRequest(client, urlString, httpVerb, msg))
framework.ExpectNoError(err, "Service didn't start within time out period. %v", pollErr)
}

// All methods for Service ProxyWithPath return 200
Expand All @@ -373,32 +353,9 @@ var _ = SIGDescribe("Proxy", func() {

urlString := f.ClientConfig().Host + "/api/v1/namespaces/" + ns + "/services/test-service/proxy/some/path/with/" + httpVerb
framework.Logf("Starting http.Client for %s", urlString)
request, err := http.NewRequest(httpVerb, urlString, nil)
framework.ExpectNoError(err, "processing request")

resp, err := client.Do(request)
framework.ExpectNoError(err, "processing response")
defer resp.Body.Close()

buf := new(bytes.Buffer)
buf.ReadFrom(resp.Body)
response := buf.String()

switch httpVerb {
case "HEAD":
framework.Logf("http.Client request:%s | StatusCode:%d", httpVerb, resp.StatusCode)
framework.ExpectEqual(resp.StatusCode, 200, "The resp.StatusCode returned: %d", resp.StatusCode)
default:
var jr *jsonResponse
err = json.Unmarshal([]byte(response), &jr)
framework.ExpectNoError(err, "Failed to process jsonResponse: %v | err: %v ", buf.String(), err)

framework.Logf("http.Client request:%s | StatusCode:%d | Response: %s | Method: %s", httpVerb, resp.StatusCode, jr.Body, jr.Method)
framework.ExpectEqual(resp.StatusCode, 200, "The resp.StatusCode returned: %d", resp.StatusCode)

framework.ExpectEqual(msg, jr.Body, "The resp.Body returned: %v", jr.Body)
framework.ExpectEqual(httpVerb, jr.Method, "The resp.Body returned: %v", jr.Body)
}

pollErr := wait.PollImmediate(requestRetryPeriod, requestRetryTimeout, validateProxyVerbRequest(client, urlString, httpVerb, msg))
framework.ExpectNoError(err, "Service didn't start within time out period. %v", pollErr)
}
})
})
Expand All @@ -424,6 +381,62 @@ func checkPodStatus(f *framework.Framework, label string) func() (bool, error) {
}
}

// validateProxyVerbRequest checks that a http request to a pod
// or service was valid for any http verb. Requires agnhost image
// with porter --json-response
func validateProxyVerbRequest(client *http.Client, urlString string, httpVerb string, msg string) func() (bool, error) {
return func() (bool, error) {
var err error

request, err := http.NewRequest(httpVerb, urlString, nil)
if err != nil {
framework.Logf("Failed to get a new request. %v", err)
return false, nil
}

resp, err := client.Do(request)
if err != nil {
framework.Logf("Failed to get a response. %v", err)
return false, nil
}
defer resp.Body.Close()

buf := new(bytes.Buffer)
buf.ReadFrom(resp.Body)
response := buf.String()

switch httpVerb {
case "HEAD":
framework.Logf("http.Client request:%s | StatusCode:%d", httpVerb, resp.StatusCode)
if resp.StatusCode != 200 {
return false, nil
}
return true, nil
default:
var jr *jsonResponse
err = json.Unmarshal([]byte(response), &jr)
if err != nil {
framework.Logf("Failed to process jsonResponse. %v", err)
return false, nil
}

framework.Logf("http.Client request:%s | StatusCode:%d | Response:%s | Method:%s", httpVerb, resp.StatusCode, jr.Body, jr.Method)
if resp.StatusCode != 200 {
return false, nil
}

if msg != jr.Body {
return false, nil
}

if httpVerb != jr.Method {
return false, nil
}
return true, nil
}
}
}

func doProxy(f *framework.Framework, path string, i int) (body []byte, statusCode int, d time.Duration, err error) {
// About all of the proxy accesses in this file:
// * AbsPath is used because it preserves the trailing '/'.
Expand Down