@@ -22,15 +22,16 @@ import (
2222 "fmt"
2323 "strings"
2424 "testing"
25+ "time"
2526
2627 v1 "k8s.io/api/core/v1"
27- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28- "k8s.io/apimachinery/pkg/runtime/schema"
28+ klabels "k8s.io/apimachinery/pkg/labels"
2929 "k8s.io/client-go/kubernetes/scheme"
3030 "k8s.io/client-go/rest"
3131 "k8s.io/client-go/tools/remotecommand"
3232 "sigs.k8s.io/controller-runtime/pkg/client"
3333
34+ "sigs.k8s.io/gateway-api/conformance/utils/config"
3435 "sigs.k8s.io/gateway-api/conformance/utils/http"
3536 "sigs.k8s.io/gateway-api/conformance/utils/suite"
3637)
@@ -40,6 +41,7 @@ import (
4041type MeshPod struct {
4142 Name string
4243 Namespace string
44+ Address string
4345 rc * rest.RESTClient
4446 rcfg * rest.Config
4547}
@@ -51,42 +53,73 @@ const (
5153 MeshAppEchoV2 MeshApplication = "app=echo,version=v2"
5254)
5355
54- func (m * MeshPod ) SendRequest (t * testing.T , exp http.ExpectedResponse ) {
55- r := exp .Request
56+ func (m * MeshPod ) MakeRequestAndExpectEventuallyConsistentResponse (t * testing.T , exp http.ExpectedResponse , timeoutConfig config.TimeoutConfig ) {
57+ t .Helper ()
58+
59+ req := makeRequest (exp .Request )
60+
61+ http .AwaitConvergence (t , timeoutConfig .RequiredConsecutiveSuccesses , timeoutConfig .MaxTimeToConsistency , func (elapsed time.Duration ) bool {
62+ resp , err := m .request (makeRequest (exp .Request ))
63+ if err != nil {
64+ t .Logf ("Request failed, not ready yet: %v (after %v)" , err .Error (), elapsed )
65+ return false
66+ }
67+ t .Logf ("Got resp %v" , resp )
68+ if err := compareRequest (exp , resp ); err != nil {
69+ t .Logf ("Response expectation failed for request: %v not ready yet: %v (after %v)" , req , err , elapsed )
70+ return false
71+ }
72+ return true
73+ })
74+
75+ t .Logf ("Request passed" )
76+ }
77+
78+ func makeRequest (r http.Request ) []string {
5679 protocol := strings .ToLower (r .Protocol )
5780 if protocol == "" {
5881 protocol = "http"
5982 }
60- args := []string {"client" , fmt .Sprintf ("%s://%s/ %s" , protocol , r .Host , r .Path )}
83+ args := []string {"client" , fmt .Sprintf ("%s://%s%s" , protocol , r .Host , r .Path )}
6184 if r .Method != "" {
6285 args = append (args , "--method=" + r .Method )
6386 }
64- if ! r .UnfollowRedirect {
65- args = append (args , "--follow-redirects" )
66- }
6787 for k , v := range r .Headers {
6888 args = append (args , "-H" , fmt .Sprintf ("%v: %v" , k , v ))
6989 }
90+ return args
91+ }
7092
71- resp , err := m .request (args )
93+ func (m * MeshPod ) SendRequest (t * testing.T , exp http.ExpectedResponse ) {
94+ resp , err := m .request (makeRequest (exp .Request ))
7295 if err != nil {
7396 t .Fatalf ("Got error: %v" , err )
7497 }
7598 t .Logf ("Got resp %v" , resp )
99+ if err := compareRequest (exp , resp ); err != nil {
100+ t .Fatalf ("expectations failed: %v" , err )
101+ }
102+ }
103+
104+ func compareRequest (exp http.ExpectedResponse , resp Response ) error {
76105 want := exp .Response
77106 if fmt .Sprint (want .StatusCode ) != resp .Code {
78- t .Errorf ("wanted status code %v, got %v" , want .StatusCode , resp .Code )
107+ return fmt .Errorf ("wanted status code %v, got %v" , want .StatusCode , resp .Code )
79108 }
80109 for _ , name := range want .AbsentHeaders {
81110 if v := resp .ResponseHeaders .Values (name ); len (v ) != 0 {
82- t .Errorf ("expected no header %q, got %v" , name , v )
111+ return fmt .Errorf ("expected no header %q, got %v" , name , v )
83112 }
84113 }
85114 for k , v := range want .Headers {
86- if got := resp .RequestHeaders .Get (k ); got != v {
87- t .Errorf ("expected header %v=%v, got %v" , k , v , got )
115+ if got := resp .ResponseHeaders .Get (k ); got != v {
116+ return fmt .Errorf ("expected header %v=%v, got %v" , k , v , got )
88117 }
89118 }
119+ if ! strings .HasPrefix (resp .Hostname , exp .Backend ) {
120+ return fmt .Errorf ("expected pod name to start with %s, got %s" , exp .Backend , resp .Hostname )
121+ }
122+ return nil
90123}
91124
92125func (m * MeshPod ) request (args []string ) (Response , error ) {
@@ -129,26 +162,25 @@ func (m *MeshPod) request(args []string) (Response, error) {
129162func ConnectToApp (t * testing.T , s * suite.ConformanceTestSuite , app MeshApplication ) MeshPod {
130163 // hardcoded, for now
131164 ns := "gateway-conformance-mesh"
132- metaList := & metav1.PartialObjectMetadataList {}
133- metaList .SetGroupVersionKind (schema.GroupVersionKind {
134- Group : "" ,
135- Version : "v1" ,
136- Kind : "PodList" ,
137- })
138165
139- err := s .Client .List (context .Background (), metaList , client .InNamespace (ns ), client .HasLabels (strings .Split (string (app ), "," )))
166+ lbls , _ := klabels .Parse (string (app ))
167+
168+ podsList := v1.PodList {}
169+ err := s .Client .List (context .Background (), & podsList , client .InNamespace (ns ), client.MatchingLabelsSelector {Selector : lbls })
140170 if err != nil {
141171 t .Fatalf ("failed to query pods in app %v" , app )
142172 }
143- if len (metaList .Items ) == 0 {
173+ if len (podsList .Items ) == 0 {
144174 t .Fatalf ("no pods found in app %v" , app )
145175 }
146- podName := metaList .Items [0 ].Name
147- podNamespace := metaList .Items [0 ].Namespace
176+ pod := podsList .Items [0 ]
177+ podName := pod .Name
178+ podNamespace := pod .Namespace
148179
149180 return MeshPod {
150181 Name : podName ,
151182 Namespace : podNamespace ,
183+ Address : pod .Status .PodIP ,
152184 rc : s .RESTClient ,
153185 rcfg : s .RestConfig ,
154186 }
0 commit comments