Skip to content
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
32 changes: 32 additions & 0 deletions samples/KubernetesIngress.Sample/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ metadata:
- another-header-value
Mode: Contains
IsCaseSensitive: false
yarp.ingress.kubernetes.io/route-queryparameters: |
- Name: the-queryparameters-key
Values:
- the-queryparameters-value
Mode: Contains
IsCaseSensitive: false
- Name: another-queryparameters-key
Values:
- another-queryparameters-value
Mode: Contains
IsCaseSensitive: false
spec:
rules:
- http:
Expand Down Expand Up @@ -86,6 +97,7 @@ The table below lists the available annotations.
|yarp.ingress.kubernetes.io/session-affinity|[SessionAffinityConfig](https://microsoft.github.io/reverse-proxy/api/Yarp.ReverseProxy.Configuration.SessionAffinityConfig.html)|
|yarp.ingress.kubernetes.io/transforms|List<Dictionary<string, string>>|
|yarp.ingress.kubernetes.io/route-headers|List<[RouteHeader](https://microsoft.github.io/reverse-proxy/api/Yarp.ReverseProxy.Configuration.RouteHeader.html)>|
|yarp.ingress.kubernetes.io/route-queryparameters|List<[RouteQueryParameter](https://microsoft.github.io/reverse-proxy/api/Yarp.ReverseProxy.Configuration.RouteQueryParameter.html)>|
|yarp.ingress.kubernetes.io/route-order|int|

#### Authorization Policy
Expand Down Expand Up @@ -213,6 +225,26 @@ yarp.ingress.kubernetes.io/route-headers: |
IsCaseSensitive: false
```

#### Route QueryParameters

`route-queryparameters` are the YAML representation of YARP [Parameter Based Routing](https://microsoft.github.io/reverse-proxy/articles/queryparameter-routing.html).

See https://microsoft.github.io/reverse-proxy/api/Yarp.ReverseProxy.Configuration.RouteQueryParameter.html.

```
yarp.ingress.kubernetes.io/route-queryparameters: |
- Name: the-queryparameter-name
Values:
- the-queryparameter-value
Mode: Contains
IsCaseSensitive: false
- Name: another-queryparameter-name
Values:
- another-queryparameter-value
Mode: Contains
IsCaseSensitive: false
```

#### Route Order

See https://microsoft.github.io/reverse-proxy/api/Yarp.ReverseProxy.Configuration.RouteConfig.html#Yarp_ReverseProxy_Configuration_RouteConfig_Order.
Expand Down
22 changes: 21 additions & 1 deletion src/Kubernetes.Controller/Converters/YarpIngressOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ internal sealed class YarpIngressOptions
public HealthCheckConfig HealthCheck { get; set; }
public Dictionary<string, string> RouteMetadata { get; set; }
public List<RouteHeader> RouteHeaders { get; set; }
public List<RouteQueryParameter> RouteQueryParameters { get; set; }
public int? RouteOrder { get; set; }
}

internal sealed class RouteHeaderWapper
internal sealed class RouteHeaderWrapper
{
public string Name { get; init; }
public List<string> Values { get; init; }
Expand All @@ -46,3 +47,22 @@ public RouteHeader ToRouteHeader()
};
}
}

internal sealed class RouteQueryParameterWrapper
{
public string Name { get; init; }
public List<string> Values { get; init; }
public QueryParameterMatchMode Mode { get; init; }
public bool IsCaseSensitive { get; init; }

public RouteQueryParameter ToRouteQueryParameter()
{
return new RouteQueryParameter
{
Name = Name,
Values = Values,
Mode = Mode,
IsCaseSensitive = IsCaseSensitive
};
}
}
12 changes: 9 additions & 3 deletions src/Kubernetes.Controller/Converters/YarpParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ private static RouteConfig CreateRoute(YarpIngressContext ingressContext, V1HTTP
{
Hosts = host is not null ? new[] { host } : Array.Empty<string>(),
Path = pathMatch,
Headers = ingressContext.Options.RouteHeaders
Headers = ingressContext.Options.RouteHeaders,
QueryParameters = ingressContext.Options.RouteQueryParameters
},
ClusterId = cluster.ClusterId,
RouteId = $"{ingressContext.Ingress.Metadata.Name}.{ingressContext.Ingress.Metadata.NamespaceProperty}:{host}{path.Path}",
Expand Down Expand Up @@ -276,8 +277,13 @@ private static YarpIngressOptions HandleAnnotations(YarpIngressContext context,
}
if (annotations.TryGetValue("yarp.ingress.kubernetes.io/route-headers", out var routeHeaders))
{
// YamlDeserializer does not support IReadOnlyList<string> in RouteHeader for now, so we use RouteHeaderWapper to solve this problem.
options.RouteHeaders = YamlDeserializer.Deserialize<List<RouteHeaderWapper>>(routeHeaders).Select(p => p.ToRouteHeader()).ToList();
// YamlDeserializer does not support IReadOnlyList<string> in RouteHeader for now, so we use RouteHeaderWrapper to solve this problem.
options.RouteHeaders = YamlDeserializer.Deserialize<List<RouteHeaderWrapper>>(routeHeaders).Select(p => p.ToRouteHeader()).ToList();
}
if (annotations.TryGetValue("yarp.ingress.kubernetes.io/route-queryparameters", out var routeQueryParameters))
{
// YamlDeserializer does not support IReadOnlyList<string> in RouteParameters for now, so we use RouterQueryParameterWrapper to solve this problem.
options.RouteQueryParameters = YamlDeserializer.Deserialize<List<RouteQueryParameterWrapper>>(routeQueryParameters).Select(p => p.ToRouteQueryParameter()).ToList();
}
if (annotations.TryGetValue("yarp.ingress.kubernetes.io/route-order", out var routeOrder))
{
Expand Down
1 change: 1 addition & 0 deletions test/Kubernetes.Tests/IngressConversionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public IngressConversionTests()
[InlineData("multiple-ingresses-one-svc")]
[InlineData("multiple-namespaces")]
[InlineData("route-metadata")]
[InlineData("route-queryparameters")]
[InlineData("route-headers")]
[InlineData("route-order")]
[InlineData("missing-svc")]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
{
"ClusterId": "frontend.default:80",
"LoadBalancingPolicy": null,
"SessionAffinity": null,
"HealthCheck": null,
"HttpClient": null,
"HttpRequest": null,
"Destinations": {
"http://10.244.2.38:80": {
"Address": "http://10.244.2.38:80",
"Health": null,
"Metadata": null
}
},
"Metadata": null
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
namespace: default
annotations:
yarp.ingress.kubernetes.io/route-metadata: |
foo: bar
another-key: another-value
yarp.ingress.kubernetes.io/route-queryparameters: |
- Name: the-queryparameter-key
Values:
- the-queryparameter-value
Mode: Contains
IsCaseSensitive: false
spec:
rules:
- http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: frontend
port:
number: 80
---
apiVersion: v1
kind: Service
metadata:
name: frontend
namespace: default
spec:
selector:
app: frontend
ports:
- name: https
port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
name: frontend
namespace: default
subsets:
- addresses:
- ip: 10.244.2.38
ports:
- name: https
port: 80
protocol: TCP
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[
{
"RouteId": "minimal-ingress.default:/foo",
"Match": {
"Methods": null,
"Hosts": [],
"Path": "/foo/{**catch-all}",
"Headers": null,
"QueryParameters": [
{
"Name": "the-queryparameter-key",
"Values": [ "the-queryparameter-value" ],
"Mode": "Contains",
"IsCaseSensitive": false
}
]
},
"Order": null,
"ClusterId": "frontend.default:80",
"AuthorizationPolicy": null,
"RateLimiterPolicy": null,
"CorsPolicy": null,
"Metadata": {
"foo": "bar",
"another-key": "another-value"
},
"Transforms": null
}
]