1use k8s_gateway_api::BackendObjectReference;
2use k8s_gateway_api::CommonRouteSpec;
3use k8s_gateway_api::HttpPathMatch;
4use k8s_gateway_api::HttpPathModifier;
5use k8s_gateway_api::HttpRequestMirrorFilter;
6use k8s_gateway_api::HttpRequestRedirectFilter;
7use k8s_gateway_api::HttpRoute;
8use k8s_gateway_api::HttpRouteFilter;
9use k8s_gateway_api::HttpRouteMatch;
10use k8s_gateway_api::HttpRouteRule;
11use k8s_gateway_api::HttpRouteSpec;
12use k8s_gateway_api::HttpUrlRewriteFilter;
13use k8s_gateway_api::LocalObjectReference;
14use k8s_gateway_api::ParentReference;
15use linkerd_policy_controller_k8s_api::{self as api};
16use linkerd_policy_test::admission;
17
18#[tokio::test(flavor = "current_thread")]
19async fn accepts_valid() {
20 admission::accepts(|ns| HttpRoute {
21 metadata: meta(&ns),
22 spec: HttpRouteSpec {
23 inner: CommonRouteSpec {
24 parent_refs: Some(vec![server_parent_ref(ns)]),
25 },
26 hostnames: None,
27 rules: Some(rules()),
28 },
29 status: None,
30 })
31 .await;
32}
33
34#[tokio::test(flavor = "current_thread")]
35async fn accepts_not_implemented_requestmirror() {
36 admission::accepts(|ns| HttpRoute {
37 metadata: meta(&ns),
38 spec: HttpRouteSpec {
39 inner: CommonRouteSpec {
40 parent_refs: Some(vec![server_parent_ref(ns)]),
41 },
42 hostnames: None,
43 rules: Some(vec![HttpRouteRule {
44 matches: Some(vec![HttpRouteMatch {
45 path: Some(HttpPathMatch::Exact {
46 value: "/foo".to_string(),
47 }),
48 ..HttpRouteMatch::default()
49 }]),
50 filters: Some(vec![HttpRouteFilter::RequestMirror {
51 request_mirror: HttpRequestMirrorFilter {
52 backend_ref: BackendObjectReference {
53 group: None,
54 kind: None,
55 namespace: Some("foo".to_string()),
56 name: "foo".to_string(),
57 port: Some(80),
58 },
59 },
60 }]),
61 backend_refs: None,
62 }]),
63 },
64 status: None,
65 })
66 .await;
67}
68
69#[tokio::test(flavor = "current_thread")]
70async fn accepts_not_implemented_urlrewrite() {
71 admission::accepts(|ns| HttpRoute {
72 metadata: api::ObjectMeta {
73 namespace: Some(ns.clone()),
74 name: Some("test".to_string()),
75 ..Default::default()
76 },
77 spec: HttpRouteSpec {
78 inner: CommonRouteSpec {
79 parent_refs: Some(vec![server_parent_ref(ns)]),
80 },
81 hostnames: None,
82 rules: Some(vec![HttpRouteRule {
83 matches: Some(vec![HttpRouteMatch {
84 path: Some(HttpPathMatch::Exact {
85 value: "/foo".to_string(),
86 }),
87 ..HttpRouteMatch::default()
88 }]),
89 filters: Some(vec![HttpRouteFilter::URLRewrite {
90 url_rewrite: HttpUrlRewriteFilter {
91 hostname: Some("foo".to_string()),
92 path: Some(HttpPathModifier::ReplaceFullPath {
93 replace_full_path: "baz".to_string(),
94 }),
95 },
96 }]),
97 backend_refs: None,
98 }]),
99 },
100 status: None,
101 })
102 .await;
103}
104
105#[tokio::test(flavor = "current_thread")]
106async fn accepts_not_implemented_extensionref() {
107 admission::accepts(|ns| HttpRoute {
108 metadata: api::ObjectMeta {
109 namespace: Some(ns.clone()),
110 name: Some("test".to_string()),
111 ..Default::default()
112 },
113 spec: HttpRouteSpec {
114 inner: CommonRouteSpec {
115 parent_refs: Some(vec![server_parent_ref(ns)]),
116 },
117 hostnames: None,
118 rules: Some(vec![HttpRouteRule {
119 matches: Some(vec![HttpRouteMatch {
120 path: Some(HttpPathMatch::Exact {
121 value: "/foo".to_string(),
122 }),
123 ..HttpRouteMatch::default()
124 }]),
125 filters: Some(vec![HttpRouteFilter::ExtensionRef {
126 extension_ref: LocalObjectReference {
127 group: "".to_string(),
128 kind: "Service".to_string(),
129 name: "foo".to_string(),
130 },
131 }]),
132 backend_refs: None,
133 }]),
134 },
135 status: None,
136 })
137 .await;
138}
139
140#[tokio::test(flavor = "current_thread")]
141async fn rejects_relative_path_match() {
142 admission::rejects(|ns| HttpRoute {
143 metadata: meta(&ns),
144 spec: HttpRouteSpec {
145 inner: CommonRouteSpec {
146 parent_refs: Some(vec![server_parent_ref(ns)]),
147 },
148 hostnames: None,
149 rules: Some(vec![HttpRouteRule {
150 matches: Some(vec![HttpRouteMatch {
151 path: Some(HttpPathMatch::Exact {
152 value: "foo/bar".to_string(),
153 }),
154 ..HttpRouteMatch::default()
155 }]),
156 filters: None,
157 backend_refs: None,
158 }]),
159 },
160 status: None,
161 })
162 .await;
163}
164
165#[tokio::test(flavor = "current_thread")]
166async fn rejects_relative_redirect_path() {
167 admission::rejects(|ns| HttpRoute {
168 metadata: meta(&ns),
169 spec: HttpRouteSpec {
170 inner: CommonRouteSpec {
171 parent_refs: Some(vec![server_parent_ref(ns)]),
172 },
173 hostnames: None,
174 rules: Some(vec![HttpRouteRule {
175 matches: Some(vec![HttpRouteMatch {
176 path: Some(HttpPathMatch::Exact {
177 value: "/foo".to_string(),
178 }),
179 ..HttpRouteMatch::default()
180 }]),
181 filters: Some(vec![HttpRouteFilter::RequestRedirect {
182 request_redirect: HttpRequestRedirectFilter {
183 scheme: None,
184 hostname: None,
185 path: Some(HttpPathModifier::ReplaceFullPath {
186 replace_full_path: "foo/bar".to_string(),
187 }),
188 port: None,
189 status_code: None,
190 },
191 }]),
192 backend_refs: None,
193 }]),
194 },
195 status: None,
196 })
197 .await;
198}
199
200fn server_parent_ref(ns: impl ToString) -> ParentReference {
201 ParentReference {
202 group: Some("policy.linkerd.io".to_string()),
203 kind: Some("Server".to_string()),
204 namespace: Some(ns.to_string()),
205 name: "my-server".to_string(),
206 section_name: None,
207 port: None,
208 }
209}
210
211fn meta(ns: impl ToString) -> api::ObjectMeta {
212 api::ObjectMeta {
213 namespace: Some(ns.to_string()),
214 name: Some("test".to_string()),
215 ..Default::default()
216 }
217}
218
219fn rules() -> Vec<HttpRouteRule> {
220 vec![HttpRouteRule {
221 matches: Some(vec![HttpRouteMatch {
222 path: Some(HttpPathMatch::Exact {
223 value: "/foo".to_string(),
224 }),
225 ..HttpRouteMatch::default()
226 }]),
227 filters: None,
228 backend_refs: None,
229 }]
230}
View as plain text