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

Three-Phase Endpoint Probing #672

Merged
merged 16 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/test-version.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ The following Gateway API version and Ingress were tested as part of the release

| Ingress | Tested version | Unavailable features |
| ------- | ----------------------- | ------------------------------ |
| Istio | v1.21.1 | retry,httpoption,update |
| Contour | v1.28.3 | httpoption,update |
| Istio | v1.21.1 | retry,httpoption |
| Contour | v1.28.3 | httpoption |
4 changes: 2 additions & 2 deletions hack/test-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@

export GATEWAY_API_VERSION="v1.0.0"
export ISTIO_VERSION="1.21.1"
export ISTIO_UNSUPPORTED_E2E_TESTS="retry,httpoption,update"
export ISTIO_UNSUPPORTED_E2E_TESTS="retry,httpoption"
export CONTOUR_VERSION="v1.28.3"
export CONTOUR_UNSUPPORTED_E2E_TESTS="httpoption,update"
export CONTOUR_UNSUPPORTED_E2E_TESTS="httpoption"
11 changes: 4 additions & 7 deletions pkg/reconciler/ingress/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,9 @@
"k8s.io/client-go/tools/cache"

"knative.dev/networking/pkg/apis/networking"
"knative.dev/networking/pkg/apis/networking/v1alpha1"
ingressinformer "knative.dev/networking/pkg/client/injection/informers/networking/v1alpha1/ingress"
ingressreconciler "knative.dev/networking/pkg/client/injection/reconciler/networking/v1alpha1/ingress"
networkcfg "knative.dev/networking/pkg/config"
"knative.dev/networking/pkg/status"
endpointsinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/endpoints"
"knative.dev/pkg/configmap"
"knative.dev/pkg/controller"
Expand All @@ -39,6 +37,7 @@
httprouteinformer "knative.dev/net-gateway-api/pkg/client/injection/informers/apis/v1beta1/httproute"
referencegrantinformer "knative.dev/net-gateway-api/pkg/client/injection/informers/apis/v1beta1/referencegrant"
"knative.dev/net-gateway-api/pkg/reconciler/ingress/config"
"knative.dev/net-gateway-api/pkg/status"
)

const (
Expand Down Expand Up @@ -105,13 +104,11 @@
statusProber := status.NewProber(
logger.Named("status-manager"),
NewProbeTargetLister(logger, endpointsInformer.Lister()),
func(ing *v1alpha1.Ingress) {
logger.Debugf("Ready callback triggered for ingress: %s/%s", ing.Namespace, ing.Name)
impl.EnqueueKey(types.NamespacedName{Namespace: ing.Namespace, Name: ing.Name})
func(ing types.NamespacedName) {
logger.Debugf("Ready callback triggered for ingress: %v", ing)
impl.EnqueueKey(ing)

Check warning on line 109 in pkg/reconciler/ingress/controller.go

View check run for this annotation

Codecov / codecov/patch

pkg/reconciler/ingress/controller.go#L108-L109

Added lines #L108 - L109 were not covered by tests
})
c.statusManager = statusProber
// TODO: Bring up gateway-api community to discuss about probing.
// related to https://github.com/knative-sandbox/net-gateway-api/issues/18
statusProber.Start(ctx.Done())

// Make sure trackers are deleted once the observers are removed.
Expand Down
232 changes: 232 additions & 0 deletions pkg/reconciler/ingress/fixtures_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
/*
Copyright 2021 The Knative Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package ingress

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
"knative.dev/networking/pkg/apis/networking"
"knative.dev/networking/pkg/http/header"
gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1"
gatewayapi "sigs.k8s.io/gateway-api/apis/v1beta1"
)

type RuleBuilder interface {
Build() gatewayapi.HTTPRouteRule
}

type HTTPRoute struct {
Namespace string
Name string
Hostnames []string
Hostname string
Rules []RuleBuilder
StatusConditions []metav1.Condition
}

func (r HTTPRoute) Build() *gatewayapi.HTTPRoute {
hostnames := r.Hostnames

if len(hostnames) == 0 && r.Hostname == "" {
hostnames = []string{"example.com"}
}

if r.Hostname != "" {
hostnames = append(hostnames, r.Hostname)
}

route := gatewayapi.HTTPRoute{
ObjectMeta: metav1.ObjectMeta{
Name: r.Name,
Namespace: r.Namespace,
Annotations: map[string]string{
networking.IngressClassAnnotationKey: gatewayAPIIngressClassName,
},
Labels: map[string]string{
networking.VisibilityLabelKey: "",
},
OwnerReferences: []metav1.OwnerReference{{
APIVersion: "networking.internal.knative.dev/v1alpha1",
Kind: "Ingress",
Name: "name",
Controller: ptr.To(true),
BlockOwnerDeletion: ptr.To(true),
}},
},
Spec: gatewayapi.HTTPRouteSpec{
CommonRouteSpec: gatewayapi.CommonRouteSpec{
ParentRefs: []gatewayapi.ParentReference{{
Group: ptr.To[gatewayapi.Group]("gateway.networking.k8s.io"),
Kind: ptr.To[gatewayapi.Kind]("Gateway"),
Namespace: ptr.To[gatewayapi.Namespace]("istio-system"),
Name: "istio-gateway",
}},
},
},
}

for _, hostname := range hostnames {
route.Spec.Hostnames = append(
route.Spec.Hostnames,
gatewayapi.Hostname(hostname),
)
}

if route.Status.Parents == nil {
route.Status.Parents = []gatewayapi.RouteParentStatus{{}}
}

route.Status.RouteStatus.Parents[0].Conditions = append(
route.Status.RouteStatus.Parents[0].Conditions,
r.StatusConditions...,
)

for _, rule := range r.Rules {
route.Spec.Rules = append(route.Spec.Rules, rule.Build())
}

return &route
}

type EndpointProbeRule struct {
Namespace string
Name string
Hash string
Path string
Port int
Headers []string
}

func (p EndpointProbeRule) Build() gatewayapi.HTTPRouteRule {
path := p.Path
if path == "" {
path = "/"
}
rule := gatewayapi.HTTPRouteRule{
Matches: []gatewayapi.HTTPRouteMatch{{
Path: &gatewayapi.HTTPPathMatch{
Type: ptr.To(gatewayapiv1.PathMatchPathPrefix),
Value: ptr.To(path),
},
Headers: []gatewayapi.HTTPHeaderMatch{{
Type: ptr.To(gatewayapiv1.HeaderMatchExact),
Name: header.HashKey,
Value: header.HashValueOverride,
}},
}},
Filters: []gatewayapi.HTTPRouteFilter{{
Type: gatewayapiv1.HTTPRouteFilterRequestHeaderModifier,
RequestHeaderModifier: &gatewayapi.HTTPHeaderFilter{
Set: []gatewayapi.HTTPHeader{{
Name: header.HashKey,
Value: p.Hash,
}},
},
}},
BackendRefs: []gatewayapi.HTTPBackendRef{{
Filters: []gatewayapiv1.HTTPRouteFilter{{
Type: gatewayapiv1.HTTPRouteFilterRequestHeaderModifier,
RequestHeaderModifier: &gatewayapi.HTTPHeaderFilter{
Set: []gatewayapi.HTTPHeader{{
Name: "K-Serving-Namespace",
Value: p.Namespace,
}, {
Name: "K-Serving-Revision",
Value: p.Name,
}},
},
}},
BackendRef: gatewayapi.BackendRef{
Weight: ptr.To[int32](100),
BackendObjectReference: gatewayapiv1.BackendObjectReference{
Group: ptr.To[gatewayapi.Group](""),
Kind: ptr.To[gatewayapi.Kind]("Service"),
Name: gatewayapi.ObjectName(p.Name),
Port: ptr.To[gatewayapi.PortNumber](gatewayapi.PortNumber(p.Port)),
},
},
}},
}

for i := 0; i < len(p.Headers); i += 2 {
k, v := p.Headers[i], p.Headers[i+1]
rule.BackendRefs[0].Filters[0].RequestHeaderModifier.Set = append(
rule.BackendRefs[0].Filters[0].RequestHeaderModifier.Set,
gatewayapi.HTTPHeader{Name: gatewayapiv1.HTTPHeaderName(k), Value: v},
)
}

return rule
}

type NormalRule struct {
Namespace string
Name string
Path string
Port int
Headers []string
Weight int
}

func (p NormalRule) Build() gatewayapi.HTTPRouteRule {
path := p.Path
if path == "" {
path = "/"
}
rule := gatewayapi.HTTPRouteRule{
Matches: []gatewayapi.HTTPRouteMatch{{
Path: &gatewayapi.HTTPPathMatch{
Type: ptr.To(gatewayapiv1.PathMatchPathPrefix),
Value: ptr.To(path),
},
}},
BackendRefs: []gatewayapi.HTTPBackendRef{{
Filters: []gatewayapiv1.HTTPRouteFilter{{
Type: gatewayapiv1.HTTPRouteFilterRequestHeaderModifier,
RequestHeaderModifier: &gatewayapi.HTTPHeaderFilter{
Set: []gatewayapi.HTTPHeader{{
Name: "K-Serving-Namespace",
Value: p.Namespace,
}, {
Name: "K-Serving-Revision",
Value: p.Name,
}},
},
}},
BackendRef: gatewayapi.BackendRef{
BackendObjectReference: gatewayapiv1.BackendObjectReference{
Group: ptr.To[gatewayapi.Group](""),
Kind: ptr.To[gatewayapi.Kind]("Service"),
Name: gatewayapi.ObjectName(p.Name),
Port: ptr.To[gatewayapi.PortNumber](gatewayapi.PortNumber(p.Port)),
},
Weight: ptr.To[int32](int32(p.Weight)),
},
},
},
}

for i := 0; i < len(p.Headers); i += 2 {
k, v := p.Headers[i], p.Headers[i+1]
rule.BackendRefs[0].Filters[0].RequestHeaderModifier.Set = append(
rule.BackendRefs[0].Filters[0].RequestHeaderModifier.Set,
gatewayapi.HTTPHeader{Name: gatewayapiv1.HTTPHeaderName(k), Value: v},
)
}

return rule
}
Loading
Loading