8000 Support empty path for ImplementationSpecific pathType (#3507) · nginx/kubernetes-ingress@54ab48c · GitHub
[go: up one dir, main page]

Skip to content

Commit 54ab48c

Browse files
authored
Support empty path for ImplementationSpecific pathType (#3507)
1 parent 43f332b commit 54ab48c

File tree

6 files changed

+48
-11
lines changed

6 files changed

+48
-11
lines changed

docs/content/configuration/ingress-resources/basic-configuration.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ Here is a breakdown of what this Ingress resource definition means:
6060
Starting from Kubernetes 1.18, you can use the following new features:
6161

6262
* The host field supports wildcard domain names, such as `*.example.com`.
63-
* The path supports different matching rules with the new field `PathType`, which takes the following values: `Prefix` for prefix-based matching, `Exact` for exact matching and `ImplementationSpecific`, which is the default type and is the same as `Prefix`. For example:
63+
* The path supports different matching rules with the new field `pathType`, which takes the following values: `Prefix` for prefix-based matching, `Exact` for exact matching and `ImplementationSpecific`, which is the default type and is the same as `Prefix`. For example:
6464
```yaml
6565
- path: /tea
6666
pathType: Prefix
@@ -105,7 +105,8 @@ Starting from Kubernetes 1.18, you can use the following new features:
105105
The NGINX Ingress Controller imposes the following restrictions on Ingress resources:
106106
* When defining an Ingress resource, the `host` field is required.
107107
* The `host` value needs to be unique among all Ingress and VirtualServer resources unless the Ingress resource is a [mergeable minion](/nginx-ingress-controller/configuration/ingress-resources/cross-namespace-configuration/). See also [Handling Host and Listener Collisions](/nginx-ingress-controller/configuration/handling-host-and-listener-collisions).
108-
* The `path` field in `spec.rules[].http.paths[]` is required.
108+
* The `path` field in `spec.rules[].http.paths[]` is required for `Exact` and `Prefix` `pathTypes`.
109+
* The ImplementationSpecific `pathType` is treated as equivilent to `Prefix` `pathType`, with the exception that when this `pathType` is configured, the `path` field in `spec.rules[].http.paths[]` is not mandatory. `path` defaults to `/` if not set but the `pathType` is set to ImplementationSpecific.
109110

110111
## Advanced Configuration
111112

internal/k8s/validation.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,7 @@ func validateIngressSpec(spec *networking.IngressSpec, fieldPath *field.Path) fi
854854
for _, path := range r.HTTP.Paths {
855855
idxPath := idxRule.Child("http").Child("path").Index(i)
856856

857-
allErrs = append(allErrs, validatePath(path.Path, idxPath.Child("path"))...)
857+
allErrs = append(allErrs, validatePath(path.Path, path.PathType, idxPath.Child("path"))...)
858858
allErrs = append(allErrs, validateBackend(&path.Backend, idxPath.Child("backend"))...)
859859
}
860860
}
@@ -879,11 +879,17 @@ const (
879879

880880
var pathRegexp = regexp.MustCompile("^" + pathFmt + "$")
881881

882-
func validatePath(path string, fieldPath *field.Path) field.ErrorList {
882+
func validatePath(path string, pathType *networking.PathType, fieldPath *field.Path) field.ErrorList {
883883
allErrs := field.ErrorList{}
884884

885+
if path == "" && pathType != nil && *pathType == networking.PathTypeImplementationSpecific {
886+
// No path defined - no further validation needed.
887+
// Path is not required for ImplementationSpecific PathType - it will default to /.
888+
return allErrs
889+
}
890+
885891
if path == "" {
886-
return append(allErrs, field.Required(fieldPath, ""))
892+
return append(allErrs, field.Required(fieldPath, "path is required for Exact and Prefix PathTypes"))
887893
}
888894

889895
if !pathRegexp.MatchString(path) {

internal/k8s/validation_test.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3420,8 +3420,10 @@ func TestValidatePath(t *testing.T) {
34203420
"/abc}{abc",
34213421
}
34223422

3423+
pathType := networking.PathTypeExact
3424+
34233425
for _, path := range validPaths {
3424-
allErrs := validatePath(path, field.NewPath("path"))
3426+
allErrs := validatePath(path, &pathType, field.NewPath("path"))
34253427
if len(allErrs) > 0 {
34263428
t.Errorf("validatePath(%q) returned errors %v for valid input", path, allErrs)
34273429
}
@@ -3440,11 +3442,18 @@ func TestValidatePath(t *testing.T) {
34403442
}
34413443

34423444
for _, path := range invalidPaths {
3443-
allErrs := validatePath(path, field.NewPath("path"))
3445+
allErrs := validatePath(path, &pathType, field.NewPath("path"))
34443446
if len(allErrs) == 0 {
34453447
t.Errorf("validatePath(%q) returned no errors for invalid input", path)
34463448
}
34473449
}
3450+
3451+
pathType = networking.PathTypeImplementationSpecific
3452+
3453+
allErrs := validatePath("", &pathType, field.NewPath("path"))
3454+
if len(allErrs) > 0 {
3455+
t.Errorf("validatePath with empty path and type ImplementationSpecific returned errors %v for valid input", allErrs)
3456+
}
34483457
}
34493458

34503459
func TestValidateCurlyBraces(t *testing.T) {

pkg/apis/configuration/validation/virtualserver_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2503,9 +2503,9 @@ func TestValidateUpstreamHealthCheck(t *testing.T) {
25032503
Value: "my.service",
25042504
},
25052505
},
2506-
StatusMatch: "! 500",
2507-
Mandatory: true,
2508-
Persistent: true,
2506+
StatusMatch: "! 500",
2507+
Mandatory: true,
2508+
Persistent: true,
25092509
KeepaliveTime: "120s",
25102510
}
25112511

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
apiVersion: networking.k8s.io/v1
2+
kind: Ingress
3+
metadata:
4+
annotations:
5+
name: smoke-ingress
6+
spec:
7+
ingressClassName: nginx
8+
tls:
9+
- hosts:
10+
- smoke.example.com
11+
secretName: smoke-secret
12+
rules:
13+
- host: smoke.example.com
14+
http:
15+
paths:
16+
- pathType: ImplementationSpecific
17+
backend:
18+
service:
19+
name: backend1-svc
20+
port:
21+
number: 80

tests/suite/test_smoke.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def __init__(self, public_endpoint: PublicEndpoint, ingress_host):
4444
self.ingress_host = ingress_host
4545

4646

47-
@pytest.fixture(scope="class", params=["standard", "mergeable"])
47+
@pytest.fixture(scope="class", params=["standard", "mergeable", "implementation-specific-pathtype"])
4848
def smoke_setup(request, kube_apis, ingress_controller_endpoint, ingress_controller, test_namespace) -> SmokeSetup:
4949
print("------------------------- Deploy Smoke Example -----------------------------------")
5050
secret_name = create_secret_from_yaml(kube_apis.v1, test_namespace, f"{TEST_DATA}/smoke/smoke-secret.yaml")

0 commit comments

Comments
 (0)
0