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

Add inherited policies for Gateway and Backends #3198

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: 4 additions & 0 deletions gwctl/pkg/printer/backends.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ func (bp *BackendsPrinter) PrintDescribeView(resourceModel *resourcediscovery.Re
policies := SortByString(maps.Values(backendNode.Policies))
pairs = append(pairs, &DescriberKV{Key: "DirectlyAttachedPolicies", Value: convertPoliciesToRefsTable(policies, false)})

// InheritedPolicies
inheritedPolicies := SortByString(maps.Values(backendNode.InheritedPolicies))
pairs = append(pairs, &DescriberKV{Key: "InheritedPolicies", Value: convertPoliciesToRefsTable(inheritedPolicies, true)})

// EffectivePolicies
if len(backendNode.EffectivePolicies) != 0 {
pairs = append(pairs, &DescriberKV{Key: "EffectivePolicies", Value: backendNode.EffectivePolicies})
Expand Down
281 changes: 280 additions & 1 deletion gwctl/pkg/printer/backends_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import (
"sigs.k8s.io/gateway-api/gwctl/pkg/utils"
)

func TestBackendsPrinter_Print(t *testing.T) {
func TestBackendsPrinter_PrintTable(t *testing.T) {
fakeClock := testingclock.NewFakeClock(time.Now())

httpRoute := func(namespace, name, serviceName, gatewayName string) *gatewayv1.HTTPRoute {
Expand Down Expand Up @@ -225,3 +225,282 @@ ns1 foo-svc-2 Service 2d ns1/foo-httproute-2, ns1/foo-httproute-3 + 2
t.Errorf("Unexpected diff\ngot=\n%v\nwant=\n%v\ndiff (-want +got)=\n%v", got2, want2, diff)
}
}

func TestBackendsPrinter_PrintDescribeView(t *testing.T) {
fakeClock := testingclock.NewFakeClock(time.Now())

crds := []runtime.Object{
&apiextensionsv1.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{
Name: "custombackendtlspolicies.gateway.networking.k8s.io",
Labels: map[string]string{
gatewayv1alpha2.PolicyLabelKey: "direct",
},
},
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
Scope: apiextensionsv1.NamespaceScoped,
Group: "gateway.networking.k8s.io",
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{{Name: "v1alpha3"}},
Names: apiextensionsv1.CustomResourceDefinitionNames{
Plural: "custombackendtlspolicies",
Kind: "CustomBackendTLSPolicy",
},
},
},
&apiextensionsv1.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{
Name: "healthcheckpolicies.foo.com",
Labels: map[string]string{
gatewayv1alpha2.PolicyLabelKey: "inherited",
},
},
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
Scope: apiextensionsv1.NamespaceScoped,
Group: "foo.com",
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{{Name: "v1"}},
Names: apiextensionsv1.CustomResourceDefinitionNames{
Plural: "healthcheckpolicies",
Kind: "HealthCheckPolicy",
},
},
},
}

objects := []runtime.Object{
&gatewayv1.GatewayClass{
TypeMeta: metav1.TypeMeta{
APIVersion: gatewayv1.GroupVersion.String(),
Kind: "GatewayClass",
},
ObjectMeta: metav1.ObjectMeta{
Name: "foo-gatewayclass",
},
Spec: gatewayv1.GatewayClassSpec{
ControllerName: "example.net/gateway-controller",
Description: common.PtrTo("random"),
},
},

common.NamespaceForTest("default"),
&gatewayv1.Gateway{
TypeMeta: metav1.TypeMeta{
APIVersion: gatewayv1.GroupVersion.String(),
Kind: "Gateway",
},
ObjectMeta: metav1.ObjectMeta{
Name: "foo-gateway",
Namespace: "default",
},
Spec: gatewayv1.GatewaySpec{
GatewayClassName: "foo-gatewayclass",
},
},
&unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "foo.com/v1",
"kind": "HealthCheckPolicy",
"metadata": map[string]interface{}{
"name": "health-check-gateway",
"namespace": "default",
},
"spec": map[string]interface{}{
"override": map[string]interface{}{
"key1": "value-parent-1",
},
"default": map[string]interface{}{
"key2": "value-parent-2",
"key5": "value-parent-5",
},
"targetRef": map[string]interface{}{
"group": "gateway.networking.k8s.io",
"kind": "Gateway",
"name": "foo-gateway",
"namespace": "default",
},
},
},
},

&gatewayv1.HTTPRoute{
TypeMeta: metav1.TypeMeta{
APIVersion: gatewayv1.GroupVersion.String(),
Kind: "HTTPRoute",
},
ObjectMeta: metav1.ObjectMeta{
Name: "foo-httproute",
Namespace: "default",
},
Spec: gatewayv1.HTTPRouteSpec{
CommonRouteSpec: gatewayv1.CommonRouteSpec{
ParentRefs: []gatewayv1.ParentReference{{
Kind: common.PtrTo(gatewayv1.Kind("Gateway")),
Group: common.PtrTo(gatewayv1.Group("gateway.networking.k8s.io")),
Name: "foo-gateway",
}},
},
Rules: []gatewayv1.HTTPRouteRule{
{
BackendRefs: []gatewayv1.HTTPBackendRef{
{
BackendRef: gatewayv1.BackendRef{
BackendObjectReference: gatewayv1.BackendObjectReference{
Port: ptr.To(gatewayv1.PortNumber(8080)),
Name: gatewayv1.ObjectName("foo-svc"),
Kind: ptr.To(gatewayv1.Kind("Service")),
},
},
},
},
},
},
},
},
&unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "foo.com/v1",
"kind": "HealthCheckPolicy",
"metadata": map[string]interface{}{
"name": "health-check-httproute",
"namespace": "default",
"creationTimestamp": fakeClock.Now().Add(-6 * 24 * time.Hour).Format(time.RFC3339),
},
"spec": map[string]interface{}{
"default": map[string]interface{}{
"key1": "value-child-1",
"key2": "value-child-2",
},
"targetRef": map[string]interface{}{
"group": "gateway.networking.k8s.io",
"kind": "HTTPRoute",
"name": "foo-httproute",
"namespace": "default",
},
},
},
},

&corev1.Service{
TypeMeta: metav1.TypeMeta{
Kind: "Service",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "foo-svc",
Namespace: "default",
UID: "00000000-0000-0000-0000-000000000001",
},
},
&unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "gateway.networking.k8s.io/v1alpha3",
"kind": "CustomBackendTLSPolicy",
"metadata": map[string]interface{}{
"name": "backend-tls-policy-1",
"namespace": "default",
},
"spec": map[string]interface{}{
"targetRef": map[string]interface{}{
"kind": "Service",
"name": "foo-svc",
"namespace": "default",
},
"validation": map[string]interface{}{
"wellKnownCACertificates": "System",
"hostname": "dev.example.com",
},
},
},
},

&corev1.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "event-1",
},
Type: corev1.EventTypeNormal,
Reason: "SYNC",
Source: corev1.EventSource{
Component: "my-gateway-controller",
},
InvolvedObject: corev1.ObjectReference{
Kind: "Service",
Name: "foo-svc",
UID: "00000000-0000-0000-0000-000000000001",
},
Message: "some random message",
},
}

var finalObjects []runtime.Object
finalObjects = append(finalObjects, crds...)
finalObjects = append(finalObjects, objects...)

k8sClients := common.MustClientsForTest(t, finalObjects...)
policyManager := utils.MustPolicyManagerForTest(t, k8sClients)
buff := &bytes.Buffer{}
discoverer := resourcediscovery.Discoverer{
K8sClients: k8sClients,
PolicyManager: policyManager,
}
resourceModel, err := discoverer.DiscoverResourcesForBackend(resourcediscovery.Filter{})
if err != nil {
t.Fatalf("Failed to construct resourceModel %v: %v", resourceModel, err)
}

bp := &BackendsPrinter{
Writer: buff,
Clock: fakeClock,
EventFetcher: discoverer,
}

bp.PrintDescribeView(resourceModel)

got := buff.String()
want := `
Name: foo-svc
Namespace: default
Labels: null
Annotations: null
Backend:
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
name: foo-svc
namespace: default
resourceVersion: "999"
uid: 00000000-0000-0000-0000-000000000001
spec: {}
status:
loadBalancer: {}
ReferencedByRoutes:
Kind Name
---- ----
HTTPRoute default/foo-httproute
DirectlyAttachedPolicies:
Type Name
---- ----
CustomBackendTLSPolicy.gateway.networking.k8s.io default/backend-tls-policy-1
InheritedPolicies:
Type Name Target Kind Target Name
---- ---- ----------- -----------
HealthCheckPolicy.foo.com default/health-check-gateway Gateway default/foo-gateway
HealthCheckPolicy.foo.com default/health-check-httproute HTTPRoute default/foo-httproute
EffectivePolicies:
default/foo-gateway:
CustomBackendTLSPolicy.gateway.networking.k8s.io:
validation:
hostname: dev.example.com
wellKnownCACertificates: System
HealthCheckPolicy.foo.com:
key1: value-parent-1
key2: value-child-2
key5: value-parent-5
Events:
Type Reason Age From Message
---- ------ --- ---- -------
Normal SYNC Unknown my-gateway-controller some random message
`
if diff := cmp.Diff(common.YamlString(want), common.YamlString(got), common.YamlStringTransformer); diff != "" {
t.Errorf("Unexpected diff\ngot=\n%v\nwant=\n%v\ndiff (-want +got)=\n%v", got, want, diff)
}
}
4 changes: 4 additions & 0 deletions gwctl/pkg/printer/gateways.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ func (gp *GatewaysPrinter) PrintDescribeView(resourceModel *resourcediscovery.Re
policies := SortByString(maps.Values(gatewayNode.Policies))
pairs = append(pairs, &DescriberKV{Key: "DirectlyAttachedPolicies", Value: convertPoliciesToRefsTable(policies, false)})

// InheritedPolicies
inheritedPolicies := SortByString(maps.Values(gatewayNode.InheritedPolicies))
pairs = append(pairs, &DescriberKV{Key: "InheritedPolicies", Value: convertPoliciesToRefsTable(inheritedPolicies, true)})

// EffectivePolicies
if len(gatewayNode.EffectivePolicies) != 0 {
pairs = append(pairs, &DescriberKV{Key: "EffectivePolicies", Value: gatewayNode.EffectivePolicies})
Expand Down
4 changes: 4 additions & 0 deletions gwctl/pkg/printer/gateways_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,10 @@ DirectlyAttachedPolicies:
Type Name
---- ----
HealthCheckPolicy.foo.com health-check-gateway
InheritedPolicies:
Type Name Target Kind Target Name
---- ---- ----------- -----------
HealthCheckPolicy.foo.com health-check-gatewayclass GatewayClass foo-gatewayclass
EffectivePolicies:
HealthCheckPolicy.foo.com:
key1: value-parent-1
Expand Down