Merge branch 'master' of github.com:traefik/traefik
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
commit
35c53a7bf3
8 changed files with 995 additions and 887 deletions
|
@ -195,40 +195,28 @@ func (s *K8sConformanceSuite) TestK8sGatewayAPIConformance() {
|
||||||
LatestObservedGenerationSet: 5 * time.Second,
|
LatestObservedGenerationSet: 5 * time.Second,
|
||||||
RequiredConsecutiveSuccesses: 0,
|
RequiredConsecutiveSuccesses: 0,
|
||||||
},
|
},
|
||||||
SupportedFeatures: sets.New[ksuite.SupportedFeature]().
|
|
||||||
Insert(ksuite.GatewayCoreFeatures.UnsortedList()...).
|
|
||||||
Insert(ksuite.ReferenceGrantCoreFeatures.UnsortedList()...),
|
|
||||||
EnableAllSupportedFeatures: false,
|
EnableAllSupportedFeatures: false,
|
||||||
RunTest: *k8sConformanceRunTest,
|
RunTest: *k8sConformanceRunTest,
|
||||||
// Until the feature are all supported, following tests are skipped.
|
// Until the feature are all supported, following tests are skipped.
|
||||||
SkipTests: []string{
|
SkipTests: []string{
|
||||||
"HTTPExactPathMatching",
|
tests.GatewayClassObservedGenerationBump.ShortName,
|
||||||
"HTTPRouteHostnameIntersection",
|
tests.GatewayWithAttachedRoutes.ShortName,
|
||||||
"HTTPRouteListenerHostnameMatching",
|
tests.GatewayModifyListeners.ShortName,
|
||||||
"HTTPRouteRequestHeaderModifier",
|
tests.GatewayInvalidTLSConfiguration.ShortName,
|
||||||
"GatewayClassObservedGenerationBump",
|
tests.HTTPRouteHostnameIntersection.ShortName,
|
||||||
"HTTPRouteInvalidNonExistentBackendRef",
|
tests.HTTPRouteListenerHostnameMatching.ShortName,
|
||||||
"GatewayWithAttachedRoutes",
|
tests.HTTPRouteInvalidNonExistentBackendRef.ShortName,
|
||||||
"HTTPRouteCrossNamespace",
|
tests.HTTPRouteInvalidReferenceGrant.ShortName,
|
||||||
"HTTPRouteDisallowedKind",
|
tests.HTTPRouteInvalidCrossNamespaceParentRef.ShortName,
|
||||||
"HTTPRouteInvalidReferenceGrant",
|
tests.HTTPRouteInvalidParentRefNotMatchingSectionName.ShortName,
|
||||||
"HTTPRouteObservedGenerationBump",
|
tests.HTTPRouteInvalidCrossNamespaceBackendRef.ShortName,
|
||||||
"TLSRouteSimpleSameNamespace",
|
tests.HTTPRouteMatchingAcrossRoutes.ShortName,
|
||||||
"TLSRouteInvalidReferenceGrant",
|
tests.HTTPRoutePartiallyInvalidViaInvalidReferenceGrant.ShortName,
|
||||||
"HTTPRouteInvalidCrossNamespaceParentRef",
|
tests.HTTPRouteRedirectHostAndStatus.ShortName,
|
||||||
"HTTPRouteInvalidParentRefNotMatchingSectionName",
|
tests.HTTPRouteInvalidBackendRefUnknownKind.ShortName,
|
||||||
"GatewayModifyListeners",
|
tests.HTTPRoutePathMatchOrder.ShortName,
|
||||||
"GatewayInvalidTLSConfiguration",
|
tests.HTTPRouteHeaderMatching.ShortName,
|
||||||
"HTTPRouteInvalidCrossNamespaceBackendRef",
|
tests.HTTPRouteReferenceGrant.ShortName,
|
||||||
"HTTPRouteMatchingAcrossRoutes",
|
|
||||||
"HTTPRoutePartiallyInvalidViaInvalidReferenceGrant",
|
|
||||||
"HTTPRouteRedirectHostAndStatus",
|
|
||||||
"HTTPRouteInvalidBackendRefUnknownKind",
|
|
||||||
"HTTPRoutePathMatchOrder",
|
|
||||||
"HTTPRouteSimpleSameNamespace",
|
|
||||||
"HTTPRouteMatching",
|
|
||||||
"HTTPRouteHeaderMatching",
|
|
||||||
"HTTPRouteReferenceGrant",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,10 +229,7 @@ func (s *K8sConformanceSuite) TestK8sGatewayAPIConformance() {
|
||||||
Version: version.Version,
|
Version: version.Version,
|
||||||
Contact: []string{"@traefik/maintainers"},
|
Contact: []string{"@traefik/maintainers"},
|
||||||
},
|
},
|
||||||
ConformanceProfiles: sets.New[ksuite.ConformanceProfileName](
|
ConformanceProfiles: sets.New(ksuite.HTTPConformanceProfileName),
|
||||||
ksuite.HTTPConformanceProfileName,
|
|
||||||
ksuite.TLSConformanceProfileName,
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
require.NoError(s.T(), err)
|
require.NoError(s.T(), err)
|
||||||
|
|
||||||
|
|
|
@ -7160,8 +7160,6 @@ func TestNodePortLB(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
test := test
|
|
||||||
|
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
kerror "k8s.io/apimachinery/pkg/api/errors"
|
kerror "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
ktypes "k8s.io/apimachinery/pkg/types"
|
||||||
kinformers "k8s.io/client-go/informers"
|
kinformers "k8s.io/client-go/informers"
|
||||||
kclientset "k8s.io/client-go/kubernetes"
|
kclientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
|
@ -51,6 +52,7 @@ type Client interface {
|
||||||
GetGatewayClasses() ([]*gatev1.GatewayClass, error)
|
GetGatewayClasses() ([]*gatev1.GatewayClass, error)
|
||||||
UpdateGatewayStatus(gateway *gatev1.Gateway, gatewayStatus gatev1.GatewayStatus) error
|
UpdateGatewayStatus(gateway *gatev1.Gateway, gatewayStatus gatev1.GatewayStatus) error
|
||||||
UpdateGatewayClassStatus(gatewayClass *gatev1.GatewayClass, condition metav1.Condition) error
|
UpdateGatewayClassStatus(gatewayClass *gatev1.GatewayClass, condition metav1.Condition) error
|
||||||
|
UpdateHTTPRouteStatus(ctx context.Context, gateway *gatev1.Gateway, nsName ktypes.NamespacedName, status gatev1.HTTPRouteStatus) error
|
||||||
GetGateways() []*gatev1.Gateway
|
GetGateways() []*gatev1.Gateway
|
||||||
GetHTTPRoutes(namespaces []string) ([]*gatev1.HTTPRoute, error)
|
GetHTTPRoutes(namespaces []string) ([]*gatev1.HTTPRoute, error)
|
||||||
GetTCPRoutes(namespaces []string) ([]*gatev1alpha2.TCPRoute, error)
|
GetTCPRoutes(namespaces []string) ([]*gatev1alpha2.TCPRoute, error)
|
||||||
|
@ -384,7 +386,7 @@ func (c *clientWrapper) GetGateways() []*gatev1.Gateway {
|
||||||
var result []*gatev1.Gateway
|
var result []*gatev1.Gateway
|
||||||
|
|
||||||
for ns, factory := range c.factoriesGateway {
|
for ns, factory := range c.factoriesGateway {
|
||||||
gateways, err := factory.Gateway().V1().Gateways().Lister().List(labels.Everything())
|
gateways, err := factory.Gateway().V1().Gateways().Lister().Gateways(ns).List(labels.Everything())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msgf("Failed to list Gateways in namespace %s", ns)
|
log.Error().Err(err).Msgf("Failed to list Gateways in namespace %s", ns)
|
||||||
continue
|
continue
|
||||||
|
@ -453,6 +455,46 @@ func (c *clientWrapper) UpdateGatewayStatus(gateway *gatev1.Gateway, gatewayStat
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *clientWrapper) UpdateHTTPRouteStatus(ctx context.Context, gateway *gatev1.Gateway, nsName ktypes.NamespacedName, status gatev1.HTTPRouteStatus) error {
|
||||||
|
if !c.isWatchedNamespace(nsName.Namespace) {
|
||||||
|
return fmt.Errorf("updating HTTPRoute status %s/%s: namespace is not within watched namespaces", nsName.Namespace, nsName.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
route, err := c.factoriesGateway[c.lookupNamespace(nsName.Namespace)].Gateway().V1().HTTPRoutes().Lister().HTTPRoutes(nsName.Namespace).Get(nsName.Name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting HTTPRoute %s/%s: %w", nsName.Namespace, nsName.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var statuses []gatev1.RouteParentStatus
|
||||||
|
for _, status := range route.Status.Parents {
|
||||||
|
if status.ControllerName != controllerName {
|
||||||
|
statuses = append(statuses, status)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if status.ParentRef.Namespace != nil && string(*status.ParentRef.Namespace) != gateway.Namespace {
|
||||||
|
statuses = append(statuses, status)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if string(status.ParentRef.Name) != gateway.Name {
|
||||||
|
statuses = append(statuses, status)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statuses = append(statuses, status.Parents...)
|
||||||
|
|
||||||
|
route = route.DeepCopy()
|
||||||
|
route.Status = gatev1.HTTPRouteStatus{
|
||||||
|
RouteStatus: gatev1.RouteStatus{
|
||||||
|
Parents: statuses,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := c.csGateway.GatewayV1().HTTPRoutes(nsName.Namespace).UpdateStatus(ctx, route, metav1.UpdateOptions{}); err != nil {
|
||||||
|
return fmt.Errorf("updating HTTPRoute %s/%s status: %w", nsName.Namespace, nsName.Name, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func statusEquals(oldStatus, newStatus gatev1.GatewayStatus) bool {
|
func statusEquals(oldStatus, newStatus gatev1.GatewayStatus) bool {
|
||||||
if len(oldStatus.Listeners) != len(newStatus.Listeners) {
|
if len(oldStatus.Listeners) != len(newStatus.Listeners) {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -1,254 +0,0 @@
|
||||||
package gateway
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
|
||||||
kscheme "k8s.io/client-go/kubernetes/scheme"
|
|
||||||
gatev1 "sigs.k8s.io/gateway-api/apis/v1"
|
|
||||||
gatev1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
|
|
||||||
gatev1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ Client = (*clientMock)(nil)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// required by k8s.MustParseYaml
|
|
||||||
err := gatev1alpha2.AddToScheme(kscheme.Scheme)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = gatev1beta1.AddToScheme(kscheme.Scheme)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = gatev1.AddToScheme(kscheme.Scheme)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type clientMock struct {
|
|
||||||
services []*corev1.Service
|
|
||||||
secrets []*corev1.Secret
|
|
||||||
endpoints []*corev1.Endpoints
|
|
||||||
namespaces []*corev1.Namespace
|
|
||||||
|
|
||||||
apiServiceError error
|
|
||||||
apiSecretError error
|
|
||||||
apiEndpointsError error
|
|
||||||
|
|
||||||
gatewayClasses []*gatev1.GatewayClass
|
|
||||||
gateways []*gatev1.Gateway
|
|
||||||
httpRoutes []*gatev1.HTTPRoute
|
|
||||||
tcpRoutes []*gatev1alpha2.TCPRoute
|
|
||||||
tlsRoutes []*gatev1alpha2.TLSRoute
|
|
||||||
referenceGrants []*gatev1beta1.ReferenceGrant
|
|
||||||
|
|
||||||
watchChan chan interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newClientMock(paths ...string) clientMock {
|
|
||||||
var c clientMock
|
|
||||||
|
|
||||||
for _, path := range paths {
|
|
||||||
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
k8sObjects := k8s.MustParseYaml(yamlContent)
|
|
||||||
for _, obj := range k8sObjects {
|
|
||||||
switch o := obj.(type) {
|
|
||||||
case *corev1.Service:
|
|
||||||
c.services = append(c.services, o)
|
|
||||||
case *corev1.Secret:
|
|
||||||
c.secrets = append(c.secrets, o)
|
|
||||||
case *corev1.Namespace:
|
|
||||||
c.namespaces = append(c.namespaces, o)
|
|
||||||
case *corev1.Endpoints:
|
|
||||||
c.endpoints = append(c.endpoints, o)
|
|
||||||
case *gatev1.GatewayClass:
|
|
||||||
c.gatewayClasses = append(c.gatewayClasses, o)
|
|
||||||
case *gatev1.Gateway:
|
|
||||||
c.gateways = append(c.gateways, o)
|
|
||||||
case *gatev1.HTTPRoute:
|
|
||||||
c.httpRoutes = append(c.httpRoutes, o)
|
|
||||||
case *gatev1alpha2.TCPRoute:
|
|
||||||
c.tcpRoutes = append(c.tcpRoutes, o)
|
|
||||||
case *gatev1alpha2.TLSRoute:
|
|
||||||
c.tlsRoutes = append(c.tlsRoutes, o)
|
|
||||||
case *gatev1beta1.ReferenceGrant:
|
|
||||||
c.referenceGrants = append(c.referenceGrants, o)
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("Unknown runtime object %+v %T", o, o))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) UpdateGatewayStatus(gateway *gatev1.Gateway, gatewayStatus gatev1.GatewayStatus) error {
|
|
||||||
for _, g := range c.gateways {
|
|
||||||
if g.Name == gateway.Name {
|
|
||||||
if !statusEquals(g.Status, gatewayStatus) {
|
|
||||||
g.Status = gatewayStatus
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fmt.Errorf("cannot update gateway %v", gateway.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) UpdateGatewayClassStatus(gatewayClass *gatev1.GatewayClass, condition metav1.Condition) error {
|
|
||||||
for _, gc := range c.gatewayClasses {
|
|
||||||
if gc.Name == gatewayClass.Name {
|
|
||||||
for _, c := range gc.Status.Conditions {
|
|
||||||
if c.Type == condition.Type && c.Status != condition.Status {
|
|
||||||
c.Status = condition.Status
|
|
||||||
c.LastTransitionTime = condition.LastTransitionTime
|
|
||||||
c.Message = condition.Message
|
|
||||||
c.Reason = condition.Reason
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) UpdateGatewayStatusConditions(gateway *gatev1.Gateway, condition metav1.Condition) error {
|
|
||||||
for _, g := range c.gatewayClasses {
|
|
||||||
if g.Name == gateway.Name {
|
|
||||||
for _, c := range g.Status.Conditions {
|
|
||||||
if c.Type == condition.Type && (c.Status != condition.Status || c.Reason != condition.Reason) {
|
|
||||||
c.Status = condition.Status
|
|
||||||
c.LastTransitionTime = condition.LastTransitionTime
|
|
||||||
c.Message = condition.Message
|
|
||||||
c.Reason = condition.Reason
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetGatewayClasses() ([]*gatev1.GatewayClass, error) {
|
|
||||||
return c.gatewayClasses, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetGateways() []*gatev1.Gateway {
|
|
||||||
return c.gateways
|
|
||||||
}
|
|
||||||
|
|
||||||
func inNamespace(m metav1.ObjectMeta, s string) bool {
|
|
||||||
return s == metav1.NamespaceAll || m.Namespace == s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetNamespaces(selector labels.Selector) ([]string, error) {
|
|
||||||
var ns []string
|
|
||||||
for _, namespace := range c.namespaces {
|
|
||||||
if selector.Matches(labels.Set(namespace.Labels)) {
|
|
||||||
ns = append(ns, namespace.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ns, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetHTTPRoutes(namespaces []string) ([]*gatev1.HTTPRoute, error) {
|
|
||||||
var httpRoutes []*gatev1.HTTPRoute
|
|
||||||
for _, namespace := range namespaces {
|
|
||||||
for _, httpRoute := range c.httpRoutes {
|
|
||||||
if inNamespace(httpRoute.ObjectMeta, namespace) {
|
|
||||||
httpRoutes = append(httpRoutes, httpRoute)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return httpRoutes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetTCPRoutes(namespaces []string) ([]*gatev1alpha2.TCPRoute, error) {
|
|
||||||
var tcpRoutes []*gatev1alpha2.TCPRoute
|
|
||||||
for _, namespace := range namespaces {
|
|
||||||
for _, tcpRoute := range c.tcpRoutes {
|
|
||||||
if inNamespace(tcpRoute.ObjectMeta, namespace) {
|
|
||||||
tcpRoutes = append(tcpRoutes, tcpRoute)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tcpRoutes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetTLSRoutes(namespaces []string) ([]*gatev1alpha2.TLSRoute, error) {
|
|
||||||
var tlsRoutes []*gatev1alpha2.TLSRoute
|
|
||||||
for _, namespace := range namespaces {
|
|
||||||
for _, tlsRoute := range c.tlsRoutes {
|
|
||||||
if inNamespace(tlsRoute.ObjectMeta, namespace) {
|
|
||||||
tlsRoutes = append(tlsRoutes, tlsRoute)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tlsRoutes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetReferenceGrants(namespace string) ([]*gatev1beta1.ReferenceGrant, error) {
|
|
||||||
var referenceGrants []*gatev1beta1.ReferenceGrant
|
|
||||||
for _, referenceGrant := range c.referenceGrants {
|
|
||||||
if inNamespace(referenceGrant.ObjectMeta, namespace) {
|
|
||||||
referenceGrants = append(referenceGrants, referenceGrant)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return referenceGrants, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetService(namespace, name string) (*corev1.Service, bool, error) {
|
|
||||||
if c.apiServiceError != nil {
|
|
||||||
return nil, false, c.apiServiceError
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, service := range c.services {
|
|
||||||
if inNamespace(service.ObjectMeta, namespace) && service.Name == name {
|
|
||||||
return service, true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, false, c.apiServiceError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error) {
|
|
||||||
if c.apiEndpointsError != nil {
|
|
||||||
return nil, false, c.apiEndpointsError
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, endpoints := range c.endpoints {
|
|
||||||
if inNamespace(endpoints.ObjectMeta, namespace) && endpoints.Name == name {
|
|
||||||
return endpoints, true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &corev1.Endpoints{}, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetSecret(namespace, name string) (*corev1.Secret, bool, error) {
|
|
||||||
if c.apiSecretError != nil {
|
|
||||||
return nil, false, c.apiSecretError
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, secret := range c.secrets {
|
|
||||||
if inNamespace(secret.ObjectMeta, namespace) && secret.Name == name {
|
|
||||||
return secret, true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error) {
|
|
||||||
return c.watchChan, nil
|
|
||||||
}
|
|
|
@ -17,17 +17,6 @@ data:
|
||||||
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
|
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
|
||||||
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=
|
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
name: supersecret
|
|
||||||
namespace: default
|
|
||||||
|
|
||||||
data:
|
|
||||||
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
|
|
||||||
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: GatewayClass
|
kind: GatewayClass
|
||||||
apiVersion: gateway.networking.k8s.io/v1
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,6 +3,8 @@ package gateway
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -12,16 +14,35 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
||||||
"github.com/traefik/traefik/v3/pkg/provider"
|
"github.com/traefik/traefik/v3/pkg/provider"
|
||||||
traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
|
traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
|
||||||
|
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
|
||||||
"github.com/traefik/traefik/v3/pkg/tls"
|
"github.com/traefik/traefik/v3/pkg/tls"
|
||||||
"github.com/traefik/traefik/v3/pkg/types"
|
"github.com/traefik/traefik/v3/pkg/types"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
kubefake "k8s.io/client-go/kubernetes/fake"
|
||||||
|
kscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
"k8s.io/utils/ptr"
|
"k8s.io/utils/ptr"
|
||||||
gatev1 "sigs.k8s.io/gateway-api/apis/v1"
|
gatev1 "sigs.k8s.io/gateway-api/apis/v1"
|
||||||
|
gatev1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
|
||||||
gatev1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
|
gatev1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
|
||||||
|
gatefake "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/fake"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ provider.Provider = (*Provider)(nil)
|
var _ provider.Provider = (*Provider)(nil)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// required by k8s.MustParseYaml
|
||||||
|
if err := gatev1.AddToScheme(kscheme.Scheme); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if err := gatev1beta1.AddToScheme(kscheme.Scheme); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if err := gatev1alpha2.AddToScheme(kscheme.Scheme); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadHTTPRoutes(t *testing.T) {
|
func TestLoadHTTPRoutes(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
|
@ -1248,10 +1269,10 @@ func TestLoadHTTPRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default-http-app-1-my-gateway-web-4a1b73e6f83804949a37": {
|
"default-http-app-1-my-gateway-web-6cf37fa71907768d925c": {
|
||||||
EntryPoints: []string{"web"},
|
EntryPoints: []string{"web"},
|
||||||
Service: "default-http-app-1-my-gateway-web-4a1b73e6f83804949a37-wrr",
|
Service: "default-http-app-1-my-gateway-web-6cf37fa71907768d925c-wrr",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/bar`) && Header(`my-header`,`foo`) && Header(`my-header2`,`bar`)",
|
Rule: "Host(`foo.com`) && (Path(`/bar`) || PathPrefix(`/bar/`)) && Header(`my-header`,`foo`) && Header(`my-header2`,`bar`)",
|
||||||
RuleSyntax: "v3",
|
RuleSyntax: "v3",
|
||||||
},
|
},
|
||||||
"default-http-app-1-my-gateway-web-aaba0f24fd26e1ca2276": {
|
"default-http-app-1-my-gateway-web-aaba0f24fd26e1ca2276": {
|
||||||
|
@ -1263,7 +1284,7 @@ func TestLoadHTTPRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default-http-app-1-my-gateway-web-4a1b73e6f83804949a37-wrr": {
|
"default-http-app-1-my-gateway-web-6cf37fa71907768d925c-wrr": {
|
||||||
Weighted: &dynamic.WeightedRoundRobin{
|
Weighted: &dynamic.WeightedRoundRobin{
|
||||||
Services: []dynamic.WRRService{
|
Services: []dynamic.WRRService{
|
||||||
{
|
{
|
||||||
|
@ -1733,9 +1754,27 @@ func TestLoadHTTPRoutes(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
p := Provider{EntryPoints: test.entryPoints, ExperimentalChannel: test.experimentalChannel}
|
p := Provider{
|
||||||
|
EntryPoints: test.entryPoints,
|
||||||
|
ExperimentalChannel: test.experimentalChannel,
|
||||||
|
}
|
||||||
|
|
||||||
conf := p.loadConfigurationFromGateway(context.Background(), newClientMock(test.paths...))
|
k8sObjects, gwObjects := readResources(t, test.paths)
|
||||||
|
|
||||||
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
|
gwClient := newGatewaySimpleClientSet(t, gwObjects...)
|
||||||
|
|
||||||
|
client := newClientImpl(kubeClient, gwClient)
|
||||||
|
|
||||||
|
eventCh, err := client.WatchAll(nil, make(chan struct{}))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if len(k8sObjects) > 0 || len(gwObjects) > 0 {
|
||||||
|
// just wait for the first event
|
||||||
|
<-eventCh
|
||||||
|
}
|
||||||
|
|
||||||
|
conf := p.loadConfigurationFromGateway(context.Background(), client)
|
||||||
assert.Equal(t, test.expected, conf)
|
assert.Equal(t, test.expected, conf)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1992,12 +2031,28 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
p := Provider{EntryPoints: test.entryPoints}
|
p := Provider{EntryPoints: test.entryPoints}
|
||||||
|
|
||||||
|
k8sObjects, gwObjects := readResources(t, test.paths)
|
||||||
|
|
||||||
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
|
gwClient := newGatewaySimpleClientSet(t, gwObjects...)
|
||||||
|
|
||||||
|
client := newClientImpl(kubeClient, gwClient)
|
||||||
|
|
||||||
|
eventCh, err := client.WatchAll(nil, make(chan struct{}))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if len(k8sObjects) > 0 || len(gwObjects) > 0 {
|
||||||
|
// just wait for the first event
|
||||||
|
<-eventCh
|
||||||
|
}
|
||||||
|
|
||||||
for group, kindFuncs := range test.groupKindBackendFuncs {
|
for group, kindFuncs := range test.groupKindBackendFuncs {
|
||||||
for kind, backendFunc := range kindFuncs {
|
for kind, backendFunc := range kindFuncs {
|
||||||
p.RegisterBackendFuncs(group, kind, backendFunc)
|
p.RegisterBackendFuncs(group, kind, backendFunc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conf := p.loadConfigurationFromGateway(context.Background(), newClientMock(test.paths...))
|
conf := p.loadConfigurationFromGateway(context.Background(), client)
|
||||||
assert.Equal(t, test.expected, conf)
|
assert.Equal(t, test.expected, conf)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2208,12 +2263,28 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
p := Provider{EntryPoints: test.entryPoints}
|
p := Provider{EntryPoints: test.entryPoints}
|
||||||
|
|
||||||
|
k8sObjects, gwObjects := readResources(t, []string{"services.yml", "httproute/filter_extension_ref.yml"})
|
||||||
|
|
||||||
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
|
gwClient := newGatewaySimpleClientSet(t, gwObjects...)
|
||||||
|
|
||||||
|
client := newClientImpl(kubeClient, gwClient)
|
||||||
|
|
||||||
|
eventCh, err := client.WatchAll(nil, make(chan struct{}))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if len(k8sObjects) > 0 || len(gwObjects) > 0 {
|
||||||
|
// just wait for the first event
|
||||||
|
<-eventCh
|
||||||
|
}
|
||||||
|
|
||||||
for group, kindFuncs := range test.groupKindFilterFuncs {
|
for group, kindFuncs := range test.groupKindFilterFuncs {
|
||||||
for kind, filterFunc := range kindFuncs {
|
for kind, filterFunc := range kindFuncs {
|
||||||
p.RegisterFilterFuncs(group, kind, filterFunc)
|
p.RegisterFilterFuncs(group, kind, filterFunc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conf := p.loadConfigurationFromGateway(context.Background(), newClientMock([]string{"services.yml", "httproute/filter_extension_ref.yml"}...))
|
conf := p.loadConfigurationFromGateway(context.Background(), client)
|
||||||
assert.Equal(t, test.expected, conf)
|
assert.Equal(t, test.expected, conf)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2971,8 +3042,28 @@ func TestLoadTCPRoutes(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
p := Provider{EntryPoints: test.entryPoints, ExperimentalChannel: true}
|
p := Provider{
|
||||||
conf := p.loadConfigurationFromGateway(context.Background(), newClientMock(test.paths...))
|
EntryPoints: test.entryPoints,
|
||||||
|
ExperimentalChannel: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
k8sObjects, gwObjects := readResources(t, test.paths)
|
||||||
|
|
||||||
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
|
gwClient := newGatewaySimpleClientSet(t, gwObjects...)
|
||||||
|
|
||||||
|
client := newClientImpl(kubeClient, gwClient)
|
||||||
|
client.experimentalChannel = true
|
||||||
|
|
||||||
|
eventCh, err := client.WatchAll(nil, make(chan struct{}))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if len(k8sObjects) > 0 || len(gwObjects) > 0 {
|
||||||
|
// just wait for the first event
|
||||||
|
<-eventCh
|
||||||
|
}
|
||||||
|
|
||||||
|
conf := p.loadConfigurationFromGateway(context.Background(), client)
|
||||||
assert.Equal(t, test.expected, conf)
|
assert.Equal(t, test.expected, conf)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -4099,8 +4190,28 @@ func TestLoadTLSRoutes(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
p := Provider{EntryPoints: test.entryPoints, ExperimentalChannel: true}
|
p := Provider{
|
||||||
conf := p.loadConfigurationFromGateway(context.Background(), newClientMock(test.paths...))
|
EntryPoints: test.entryPoints,
|
||||||
|
ExperimentalChannel: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
k8sObjects, gwObjects := readResources(t, test.paths)
|
||||||
|
|
||||||
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
|
gwClient := newGatewaySimpleClientSet(t, gwObjects...)
|
||||||
|
|
||||||
|
client := newClientImpl(kubeClient, gwClient)
|
||||||
|
client.experimentalChannel = true
|
||||||
|
|
||||||
|
eventCh, err := client.WatchAll(nil, make(chan struct{}))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if len(k8sObjects) > 0 || len(gwObjects) > 0 {
|
||||||
|
// just wait for the first event
|
||||||
|
<-eventCh
|
||||||
|
}
|
||||||
|
|
||||||
|
conf := p.loadConfigurationFromGateway(context.Background(), client)
|
||||||
assert.Equal(t, test.expected, conf)
|
assert.Equal(t, test.expected, conf)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -5112,8 +5223,28 @@ func TestLoadMixedRoutes(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
p := Provider{EntryPoints: test.entryPoints, ExperimentalChannel: test.experimentalChannel}
|
p := Provider{
|
||||||
conf := p.loadConfigurationFromGateway(context.Background(), newClientMock(test.paths...))
|
EntryPoints: test.entryPoints,
|
||||||
|
ExperimentalChannel: test.experimentalChannel,
|
||||||
|
}
|
||||||
|
|
||||||
|
k8sObjects, gwObjects := readResources(t, test.paths)
|
||||||
|
|
||||||
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
|
gwClient := newGatewaySimpleClientSet(t, gwObjects...)
|
||||||
|
|
||||||
|
client := newClientImpl(kubeClient, gwClient)
|
||||||
|
client.experimentalChannel = test.experimentalChannel
|
||||||
|
|
||||||
|
eventCh, err := client.WatchAll(nil, make(chan struct{}))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if len(k8sObjects) > 0 || len(gwObjects) > 0 {
|
||||||
|
// just wait for the first event
|
||||||
|
<-eventCh
|
||||||
|
}
|
||||||
|
|
||||||
|
conf := p.loadConfigurationFromGateway(context.Background(), client)
|
||||||
assert.Equal(t, test.expected, conf)
|
assert.Equal(t, test.expected, conf)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -5303,8 +5434,28 @@ func TestLoadRoutesWithReferenceGrants(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
p := Provider{EntryPoints: test.entryPoints, ExperimentalChannel: test.experimentalChannel}
|
p := Provider{
|
||||||
conf := p.loadConfigurationFromGateway(context.Background(), newClientMock(test.paths...))
|
EntryPoints: test.entryPoints,
|
||||||
|
ExperimentalChannel: test.experimentalChannel,
|
||||||
|
}
|
||||||
|
|
||||||
|
k8sObjects, gwObjects := readResources(t, test.paths)
|
||||||
|
|
||||||
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
|
gwClient := newGatewaySimpleClientSet(t, gwObjects...)
|
||||||
|
|
||||||
|
client := newClientImpl(kubeClient, gwClient)
|
||||||
|
client.experimentalChannel = test.experimentalChannel
|
||||||
|
|
||||||
|
eventCh, err := client.WatchAll(nil, make(chan struct{}))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if len(k8sObjects) > 0 || len(gwObjects) > 0 {
|
||||||
|
// just wait for the first event
|
||||||
|
<-eventCh
|
||||||
|
}
|
||||||
|
|
||||||
|
conf := p.loadConfigurationFromGateway(context.Background(), client)
|
||||||
assert.Equal(t, test.expected, conf)
|
assert.Equal(t, test.expected, conf)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -5731,7 +5882,8 @@ func Test_shouldAttach(t *testing.T) {
|
||||||
listener gatev1.Listener
|
listener gatev1.Listener
|
||||||
routeNamespace string
|
routeNamespace string
|
||||||
routeSpec gatev1.CommonRouteSpec
|
routeSpec gatev1.CommonRouteSpec
|
||||||
expectedAttach bool
|
wantAttach bool
|
||||||
|
wantParentRef gatev1.ParentReference
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "No ParentRefs",
|
desc: "No ParentRefs",
|
||||||
|
@ -5748,7 +5900,7 @@ func Test_shouldAttach(t *testing.T) {
|
||||||
routeSpec: gatev1.CommonRouteSpec{
|
routeSpec: gatev1.CommonRouteSpec{
|
||||||
ParentRefs: nil,
|
ParentRefs: nil,
|
||||||
},
|
},
|
||||||
expectedAttach: false,
|
wantAttach: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Unsupported Kind",
|
desc: "Unsupported Kind",
|
||||||
|
@ -5773,7 +5925,7 @@ func Test_shouldAttach(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedAttach: false,
|
wantAttach: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Unsupported Group",
|
desc: "Unsupported Group",
|
||||||
|
@ -5798,7 +5950,7 @@ func Test_shouldAttach(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedAttach: false,
|
wantAttach: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Kind is nil",
|
desc: "Kind is nil",
|
||||||
|
@ -5822,7 +5974,7 @@ func Test_shouldAttach(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedAttach: false,
|
wantAttach: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Group is nil",
|
desc: "Group is nil",
|
||||||
|
@ -5846,7 +5998,7 @@ func Test_shouldAttach(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedAttach: false,
|
wantAttach: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "SectionName does not match a listener desc",
|
desc: "SectionName does not match a listener desc",
|
||||||
|
@ -5871,7 +6023,7 @@ func Test_shouldAttach(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedAttach: false,
|
wantAttach: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Namespace does not match the Gateway namespace",
|
desc: "Namespace does not match the Gateway namespace",
|
||||||
|
@ -5896,7 +6048,7 @@ func Test_shouldAttach(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedAttach: false,
|
wantAttach: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Route namespace does not match the Gateway namespace",
|
desc: "Route namespace does not match the Gateway namespace",
|
||||||
|
@ -5920,7 +6072,7 @@ func Test_shouldAttach(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedAttach: false,
|
wantAttach: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Unsupported Kind",
|
desc: "Unsupported Kind",
|
||||||
|
@ -5945,7 +6097,7 @@ func Test_shouldAttach(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedAttach: false,
|
wantAttach: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Route namespace matches the Gateway namespace",
|
desc: "Route namespace matches the Gateway namespace",
|
||||||
|
@ -5969,7 +6121,13 @@ func Test_shouldAttach(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedAttach: true,
|
wantAttach: true,
|
||||||
|
wantParentRef: gatev1.ParentReference{
|
||||||
|
SectionName: sectionNamePtr("foo"),
|
||||||
|
Name: "gateway",
|
||||||
|
Kind: kindPtr("Gateway"),
|
||||||
|
Group: groupPtr(gatev1.GroupName),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Namespace matches the Gateway namespace",
|
desc: "Namespace matches the Gateway namespace",
|
||||||
|
@ -5994,7 +6152,14 @@ func Test_shouldAttach(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedAttach: true,
|
wantAttach: true,
|
||||||
|
wantParentRef: gatev1.ParentReference{
|
||||||
|
SectionName: sectionNamePtr("foo"),
|
||||||
|
Name: "gateway",
|
||||||
|
Namespace: namespacePtr("default"),
|
||||||
|
Kind: kindPtr("Gateway"),
|
||||||
|
Group: groupPtr(gatev1.GroupName),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Only one ParentRef matches the Gateway",
|
desc: "Only one ParentRef matches the Gateway",
|
||||||
|
@ -6024,7 +6189,13 @@ func Test_shouldAttach(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedAttach: true,
|
wantAttach: true,
|
||||||
|
wantParentRef: gatev1.ParentReference{
|
||||||
|
Name: "gateway",
|
||||||
|
Namespace: namespacePtr("default"),
|
||||||
|
Kind: kindPtr("Gateway"),
|
||||||
|
Group: groupPtr(gatev1.GroupName),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6032,8 +6203,9 @@ func Test_shouldAttach(t *testing.T) {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
got := shouldAttach(test.gateway, test.listener, test.routeNamespace, test.routeSpec)
|
gotParentRef, gotAttach := shouldAttach(test.gateway, test.listener, test.routeNamespace, test.routeSpec)
|
||||||
assert.Equal(t, test.expectedAttach, got)
|
assert.Equal(t, test.wantAttach, gotAttach)
|
||||||
|
assert.Equal(t, test.wantParentRef, gotParentRef)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6627,7 +6799,22 @@ func Test_gatewayAddresses(t *testing.T) {
|
||||||
|
|
||||||
p := Provider{StatusAddress: test.statusAddress}
|
p := Provider{StatusAddress: test.statusAddress}
|
||||||
|
|
||||||
got, err := p.gatewayAddresses(newClientMock(test.paths...))
|
k8sObjects, gwObjects := readResources(t, test.paths)
|
||||||
|
|
||||||
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
|
gwClient := newGatewaySimpleClientSet(t, gwObjects...)
|
||||||
|
|
||||||
|
client := newClientImpl(kubeClient, gwClient)
|
||||||
|
|
||||||
|
eventCh, err := client.WatchAll(nil, make(chan struct{}))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if len(k8sObjects) > 0 || len(gwObjects) > 0 {
|
||||||
|
// just wait for the first event
|
||||||
|
<-eventCh
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err := p.gatewayAddresses(client)
|
||||||
test.wantErr(t, err)
|
test.wantErr(t, err)
|
||||||
|
|
||||||
assert.Equal(t, test.want, got)
|
assert.Equal(t, test.want, got)
|
||||||
|
@ -6662,3 +6849,46 @@ func headerMatchTypePtr(h gatev1.HeaderMatchType) *gatev1.HeaderMatchType { retu
|
||||||
func objectNamePtr(objectName gatev1.ObjectName) *gatev1.ObjectName {
|
func objectNamePtr(objectName gatev1.ObjectName) *gatev1.ObjectName {
|
||||||
return &objectName
|
return &objectName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We cannot use the gateway-api fake.NewSimpleClientset due to Gateway being pluralized as "gatewaies" instead of "gateways".
|
||||||
|
func newGatewaySimpleClientSet(t *testing.T, objects ...runtime.Object) *gatefake.Clientset {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
client := gatefake.NewSimpleClientset(objects...)
|
||||||
|
for _, object := range objects {
|
||||||
|
gateway, ok := object.(*gatev1.Gateway)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := client.GatewayV1().Gateways(gateway.Namespace).Create(context.Background(), gateway, metav1.CreateOptions{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
func readResources(t *testing.T, paths []string) ([]runtime.Object, []runtime.Object) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
var k8sObjects []runtime.Object
|
||||||
|
var gwObjects []runtime.Object
|
||||||
|
for _, path := range paths {
|
||||||
|
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
objects := k8s.MustParseYaml(yamlContent)
|
||||||
|
for _, obj := range objects {
|
||||||
|
switch obj.GetObjectKind().GroupVersionKind().Group {
|
||||||
|
case "gateway.networking.k8s.io":
|
||||||
|
gwObjects = append(gwObjects, obj)
|
||||||
|
default:
|
||||||
|
k8sObjects = append(k8sObjects, obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return k8sObjects, gwObjects
|
||||||
|
}
|
||||||
|
|
|
@ -1725,8 +1725,6 @@ func TestLoadConfigurationFromIngressesWithNodePortLB(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
test := test
|
|
||||||
|
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue