Skip to content

Commit 5e5359a

Browse files
authored
Merge pull request #103 from tpantelis/headless_dns
Add conformance tests for headless DNS
2 parents 6c631f4 + e7f6409 commit 5e5359a

File tree

7 files changed

+422
-74
lines changed

7 files changed

+422
-74
lines changed

conformance/clusterip_service_dns.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ var _ = Describe("", Label(OptionalLabel, DNSLabel, ClusterIPLabel), func() {
5858
By(fmt.Sprintf("Found ServiceImport on cluster %q with clusterset IP %q", client.name, clusterSetIP))
5959
By(fmt.Sprintf("Executing command %q on cluster %q", strings.Join(command, " "), client.name))
6060

61-
t.awaitCmdOutputContains(&client, command, clusterSetIP, 1, reportNonConformant(""))
61+
t.awaitCmdOutputMatches(&client, command, clusterSetIP, 1, reportNonConformant(""))
6262
}
6363
})
6464

@@ -104,7 +104,7 @@ var _ = Describe("", Label(OptionalLabel, DNSLabel, ClusterIPLabel), func() {
104104

105105
By(fmt.Sprintf("Executing command %q on cluster %q", strings.Join(command, " "), clients[0].name))
106106

107-
t.awaitCmdOutputContains(&clients[0], command, resolvedIP, 1, reportNonConformant(""))
107+
t.awaitCmdOutputMatches(&clients[0], command, resolvedIP, 1, reportNonConformant(""))
108108
})
109109
})
110110

@@ -135,6 +135,10 @@ type srvRecord struct {
135135
domainName string
136136
}
137137

138+
func (s srvRecord) String() string {
139+
return fmt.Sprintf("port:%d, domainName:%q", s.port, s.domainName)
140+
}
141+
138142
func parseSRVRecords(str string) []srvRecord {
139143
var recs []srvRecord
140144

conformance/conformance_suite.go

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import (
3030

3131
. "github.com/onsi/ginkgo/v2"
3232
. "github.com/onsi/gomega"
33+
"github.com/onsi/gomega/types"
34+
appsv1 "k8s.io/api/apps/v1"
3335
corev1 "k8s.io/api/core/v1"
3436
discoveryv1 "k8s.io/api/discovery/v1"
3537
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -143,9 +145,10 @@ func setupClients() error {
143145
}
144146

145147
type testDriver struct {
146-
namespace string
147-
helloService *corev1.Service
148-
requestPod *corev1.Pod
148+
namespace string
149+
helloService *corev1.Service
150+
helloDeployment *appsv1.Deployment
151+
requestPod *corev1.Pod
149152
}
150153

151154
func newTestDriver() *testDriver {
@@ -154,6 +157,7 @@ func newTestDriver() *testDriver {
154157
BeforeEach(func() {
155158
t.namespace = fmt.Sprintf("mcs-conformance-%v", rand.Uint32())
156159
t.helloService = newHelloService()
160+
t.helloDeployment = newHelloDeployment()
157161
t.requestPod = newRequestPod()
158162
})
159163

@@ -202,9 +206,12 @@ func (t *testDriver) deleteServiceExport(c *clusterClients) {
202206
}
203207

204208
func (t *testDriver) deployHelloService(c *clusterClients, service *corev1.Service) {
205-
_, err := c.k8s.AppsV1().Deployments(t.namespace).Create(ctx, newHelloDeployment(), metav1.CreateOptions{})
206-
Expect(err).ToNot(HaveOccurred())
207-
_, err = c.k8s.CoreV1().Services(t.namespace).Create(ctx, service, metav1.CreateOptions{})
209+
if t.helloDeployment != nil {
210+
_, err := c.k8s.AppsV1().Deployments(t.namespace).Create(ctx, t.helloDeployment, metav1.CreateOptions{})
211+
Expect(err).ToNot(HaveOccurred())
212+
}
213+
214+
_, err := c.k8s.CoreV1().Services(t.namespace).Create(ctx, service, metav1.CreateOptions{})
208215
Expect(err).ToNot(HaveOccurred())
209216
}
210217

@@ -293,10 +300,19 @@ func (t *testDriver) execCmdOnRequestPod(c *clusterClients, command []string) st
293300
return string(stdout)
294301
}
295302

296-
func (t *testDriver) awaitCmdOutputContains(c *clusterClients, command []string, expectedString string, nIter int, msg func() string) {
303+
func (t *testDriver) awaitCmdOutputMatches(c *clusterClients, command []string, expected any, nIter int, msg func() string) {
304+
var matcher types.GomegaMatcher
305+
306+
switch v := expected.(type) {
307+
case string:
308+
matcher = ContainSubstring(v)
309+
case types.GomegaMatcher:
310+
matcher = v
311+
}
312+
297313
Eventually(func(g Gomega) {
298314
output := t.execCmdOnRequestPod(c, command)
299-
g.Expect(output).To(ContainSubstring(expectedString), "Command output")
315+
g.Expect(output).To(matcher, "Command output")
300316
}).Within(time.Duration(20*int64(nIter))*time.Second).ProbeEvery(time.Second).MustPassRepeatedly(nIter).Should(Succeed(), msg)
301317
}
302318

conformance/connectivity.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ var _ = Describe("", func() {
6464
for _, client := range clients {
6565
By(fmt.Sprintf("Executing command %q on cluster %q", strings.Join(command, " "), client.name))
6666

67-
t.awaitCmdOutputContains(&client, command, "pod ip", 1, reportNonConformant(""))
67+
t.awaitCmdOutputMatches(&client, command, "pod ip", 1, reportNonConformant(""))
6868
}
6969
})
7070
})
@@ -111,7 +111,7 @@ var _ = Describe("", func() {
111111
for _, client := range clients {
112112
By(fmt.Sprintf("Executing command %q on cluster %q", strings.Join(command, " "), client.name))
113113

114-
t.awaitCmdOutputContains(&client, command, servicePodIP, 10, reportNonConformant(""))
114+
t.awaitCmdOutputMatches(&client, command, servicePodIP, 10, reportNonConformant(""))
115115
}
116116
})
117117
})

conformance/endpoint_slice.go

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package conformance
1818

1919
import (
20-
"context"
2120
"fmt"
2221
"time"
2322

@@ -26,7 +25,6 @@ import (
2625
discoveryv1 "k8s.io/api/discovery/v1"
2726
apierrors "k8s.io/apimachinery/pkg/api/errors"
2827
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29-
"k8s.io/apimachinery/pkg/util/wait"
3028
"sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
3129
)
3230

@@ -47,24 +45,19 @@ var _ = Describe("", Label(OptionalLabel, EndpointSliceLabel), func() {
4745
endpointSlices := make([]*discoveryv1.EndpointSlice, len(clients))
4846

4947
for i, client := range clients {
50-
eps := t.awaitMCSEndpointSlice(&client)
51-
Expect(eps).ToNot(BeNil(), reportNonConformant(fmt.Sprintf(
48+
eps := t.awaitMCSEndpointSlice(&client, discoveryv1.AddressTypeIPv4, nil, reportNonConformant(fmt.Sprintf(
5249
"an MCS EndpointSlice was not found on cluster %q. An MCS EndpointSlice is identified by the presence "+
53-
"of at least one of the required MCS labels, whose names are prefixed with \"multicluster.kubernetes.io\". "+
50+
"of the required MCS labels (%q and %q). "+
5451
"If the MCS implementation does not use MCS EndpointSlices, you can specify a Ginkgo label filter using "+
5552
"the %q label where appropriate to skip this test.",
56-
client.name, EndpointSliceLabel)))
53+
client.name, v1alpha1.LabelServiceName, v1alpha1.LabelSourceCluster, EndpointSliceLabel)))
5754

5855
endpointSlices[i] = eps
5956

6057
Expect(eps.Labels).To(HaveKeyWithValue(v1alpha1.LabelServiceName, t.helloService.Name),
6158
reportNonConformant(fmt.Sprintf("the MCS EndpointSlice %q does not contain the %q label referencing the service name",
6259
eps.Name, v1alpha1.LabelServiceName)))
6360

64-
Expect(eps.Labels).To(HaveKey(v1alpha1.LabelSourceCluster),
65-
reportNonConformant(fmt.Sprintf("the MCS EndpointSlice %q does not contain the %q label",
66-
eps.Name, v1alpha1.LabelSourceCluster)))
67-
6861
Expect(eps.Labels).To(HaveKey(discoveryv1.LabelManagedBy),
6962
reportNonConformant(fmt.Sprintf("the MCS EndpointSlice %q does not contain the %q label",
7063
eps.Name, discoveryv1.LabelManagedBy)))
@@ -90,32 +83,38 @@ var _ = Describe("", Label(OptionalLabel, EndpointSliceLabel), func() {
9083
})
9184
})
9285

93-
func (t *testDriver) awaitMCSEndpointSlice(c *clusterClients) *discoveryv1.EndpointSlice {
86+
func (t *testDriver) awaitMCSEndpointSlice(c *clusterClients, addressType discoveryv1.AddressType,
87+
verify func(Gomega, *discoveryv1.EndpointSlice), desc ...any) *discoveryv1.EndpointSlice {
9488
var endpointSlice *discoveryv1.EndpointSlice
9589

9690
hasLabel := func(eps *discoveryv1.EndpointSlice, label string) bool {
9791
_, exists := eps.Labels[label]
9892
return exists
9993
}
10094

101-
_ = wait.PollUntilContextTimeout(ctx, 100*time.Millisecond,
102-
20*time.Second, true, func(ctx context.Context) (bool, error) {
103-
defer GinkgoRecover()
95+
Eventually(func(g Gomega) {
96+
list, err := c.k8s.DiscoveryV1().EndpointSlices(t.namespace).List(ctx, metav1.ListOptions{})
97+
g.Expect(err).ToNot(HaveOccurred(), "Error retrieving EndpointSlices")
98+
99+
endpointSlice = nil
104100

105-
list, err := c.k8s.DiscoveryV1().EndpointSlices(t.namespace).List(ctx, metav1.ListOptions{})
106-
Expect(err).ToNot(HaveOccurred(), "Error retrieving EndpointSlices")
101+
for i := range list.Items {
102+
eps := &list.Items[i]
107103

108-
for i := range list.Items {
109-
eps := &list.Items[i]
104+
if hasLabel(eps, v1alpha1.LabelServiceName) && hasLabel(eps, v1alpha1.LabelSourceCluster) && eps.AddressType == addressType {
105+
endpointSlice = eps
110106

111-
if hasLabel(eps, v1alpha1.LabelServiceName) || hasLabel(eps, v1alpha1.LabelSourceCluster) {
112-
endpointSlice = eps
113-
return true, nil
107+
if verify != nil {
108+
verify(g, endpointSlice)
114109
}
115110
}
111+
}
112+
113+
g.Expect(endpointSlice).ToNot(BeNil(), desc...)
116114

117-
return false, nil
118-
})
115+
// The final run succeeded so cancel any prior non-conformance reported.
116+
cancelNonConformanceReport()
117+
}).Within(20 * time.Second).ProbeEvery(100 * time.Millisecond).Should(Succeed())
119118

120119
return endpointSlice
121120
}

0 commit comments

Comments
 (0)