├── .dockerignore
├── .github
└── workflows
│ └── test.yaml
├── .gitignore
├── .idea
├── .gitignore
├── modules.xml
├── qmlSettings.xml
├── tolerable.iml
└── vcs.xml
├── Cargo.lock
├── Cargo.toml
├── Dockerfile
├── LICENSE.md
├── README.md
├── build.rs
├── docker
└── tolerable.toml
├── justfile
├── kustomize
├── certificate.webhook.yaml
├── deployment.tolerable.yaml
├── deployment.ubuntu-test.yaml
├── issuer.selfsigned.yaml
├── kustomization.yaml
├── mutatingwebhook.yaml
├── ns.tolerable.yaml
├── service.tolerable.yaml
├── svcacct.tolerable.yaml
└── tolerable.toml
├── src
├── consts.rs
├── main.rs
├── manifest.rs
├── metrics.rs
├── models.rs
├── mutation.rs
└── tests
│ ├── admission-review-not-pod.json
│ ├── admission-review-pod-half-arm.json
│ ├── admission-review-pod-match.json
│ ├── admission-review-pod.json
│ ├── mod.rs
│ ├── test_bl.rs
│ └── test_serde.rs
├── tolerable.toml
└── tools
└── target_arch.sh
/.dockerignore:
--------------------------------------------------------------------------------
1 | target/**/deps
2 | target/**/build
3 | target/debug
4 | target/**/.fingerprint
5 |
--------------------------------------------------------------------------------
/.github/workflows/test.yaml:
--------------------------------------------------------------------------------
1 | env:
2 | RUST_LOG: debug
3 | TOLERABLE_SUPPORTED_ARCHITECTURES: "arm64"
4 | on:
5 | push: {}
6 | pull_request:
7 | branches: [ "main" ]
8 | name: Run Tests
9 | jobs:
10 | test:
11 | name: tolerable
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v2
15 | - uses: actions-rs/toolchain@v1
16 | with:
17 | toolchain: stable
18 | - uses: timheuer/base64-to-file@v1.2
19 | with:
20 | fileName: 'docker.io.toml'
21 | fileDir: './creds/'
22 | encodedString: ${{ secrets.DOCKER_IO_CREDS }}
23 | - uses: actions-rs/cargo@v1
24 | with:
25 | command: test
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | /cfssl
3 | /creds
4 | .secrets
5 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/qmlSettings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/tolerable.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 3
4 |
5 | [[package]]
6 | name = "actix-codec"
7 | version = "0.5.0"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "57a7559404a7f3573127aab53c08ce37a6c6a315c374a31070f3c91cd1b4a7fe"
10 | dependencies = [
11 | "bitflags",
12 | "bytes",
13 | "futures-core",
14 | "futures-sink",
15 | "log",
16 | "memchr",
17 | "pin-project-lite",
18 | "tokio",
19 | "tokio-util",
20 | ]
21 |
22 | [[package]]
23 | name = "actix-http"
24 | version = "3.3.1"
25 | source = "registry+https://github.com/rust-lang/crates.io-index"
26 | checksum = "c2079246596c18b4a33e274ae10c0e50613f4d32a4198e09c7b93771013fed74"
27 | dependencies = [
28 | "actix-codec",
29 | "actix-rt",
30 | "actix-service",
31 | "actix-tls",
32 | "actix-utils",
33 | "ahash 0.8.3",
34 | "base64 0.21.0",
35 | "bitflags",
36 | "brotli",
37 | "bytes",
38 | "bytestring",
39 | "derive_more",
40 | "encoding_rs",
41 | "flate2",
42 | "futures-core",
43 | "h2",
44 | "http",
45 | "httparse",
46 | "httpdate",
47 | "itoa",
48 | "language-tags",
49 | "local-channel",
50 | "mime",
51 | "percent-encoding",
52 | "pin-project-lite",
53 | "rand",
54 | "sha1",
55 | "smallvec",
56 | "tokio",
57 | "tokio-util",
58 | "tracing",
59 | "zstd",
60 | ]
61 |
62 | [[package]]
63 | name = "actix-macros"
64 | version = "0.2.3"
65 | source = "registry+https://github.com/rust-lang/crates.io-index"
66 | checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6"
67 | dependencies = [
68 | "quote",
69 | "syn",
70 | ]
71 |
72 | [[package]]
73 | name = "actix-router"
74 | version = "0.5.1"
75 | source = "registry+https://github.com/rust-lang/crates.io-index"
76 | checksum = "d66ff4d247d2b160861fa2866457e85706833527840e4133f8f49aa423a38799"
77 | dependencies = [
78 | "bytestring",
79 | "http",
80 | "regex",
81 | "serde",
82 | "tracing",
83 | ]
84 |
85 | [[package]]
86 | name = "actix-rt"
87 | version = "2.8.0"
88 | source = "registry+https://github.com/rust-lang/crates.io-index"
89 | checksum = "15265b6b8e2347670eb363c47fc8c75208b4a4994b27192f345fcbe707804f3e"
90 | dependencies = [
91 | "futures-core",
92 | "tokio",
93 | ]
94 |
95 | [[package]]
96 | name = "actix-server"
97 | version = "2.2.0"
98 | source = "registry+https://github.com/rust-lang/crates.io-index"
99 | checksum = "3e8613a75dd50cc45f473cee3c34d59ed677c0f7b44480ce3b8247d7dc519327"
100 | dependencies = [
101 | "actix-rt",
102 | "actix-service",
103 | "actix-utils",
104 | "futures-core",
105 | "futures-util",
106 | "mio",
107 | "num_cpus",
108 | "socket2",
109 | "tokio",
110 | "tracing",
111 | ]
112 |
113 | [[package]]
114 | name = "actix-service"
115 | version = "2.0.2"
116 | source = "registry+https://github.com/rust-lang/crates.io-index"
117 | checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a"
118 | dependencies = [
119 | "futures-core",
120 | "paste",
121 | "pin-project-lite",
122 | ]
123 |
124 | [[package]]
125 | name = "actix-tls"
126 | version = "3.0.3"
127 | source = "registry+https://github.com/rust-lang/crates.io-index"
128 | checksum = "9fde0cf292f7cdc7f070803cb9a0d45c018441321a78b1042ffbbb81ec333297"
129 | dependencies = [
130 | "actix-codec",
131 | "actix-rt",
132 | "actix-service",
133 | "actix-utils",
134 | "futures-core",
135 | "http",
136 | "log",
137 | "pin-project-lite",
138 | "tokio-rustls",
139 | "tokio-util",
140 | "webpki-roots",
141 | ]
142 |
143 | [[package]]
144 | name = "actix-utils"
145 | version = "3.0.1"
146 | source = "registry+https://github.com/rust-lang/crates.io-index"
147 | checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8"
148 | dependencies = [
149 | "local-waker",
150 | "pin-project-lite",
151 | ]
152 |
153 | [[package]]
154 | name = "actix-web"
155 | version = "4.3.1"
156 | source = "registry+https://github.com/rust-lang/crates.io-index"
157 | checksum = "cd3cb42f9566ab176e1ef0b8b3a896529062b4efc6be0123046095914c4c1c96"
158 | dependencies = [
159 | "actix-codec",
160 | "actix-http",
161 | "actix-macros",
162 | "actix-router",
163 | "actix-rt",
164 | "actix-server",
165 | "actix-service",
166 | "actix-tls",
167 | "actix-utils",
168 | "actix-web-codegen",
169 | "ahash 0.7.6",
170 | "bytes",
171 | "bytestring",
172 | "cfg-if",
173 | "cookie",
174 | "derive_more",
175 | "encoding_rs",
176 | "futures-core",
177 | "futures-util",
178 | "http",
179 | "itoa",
180 | "language-tags",
181 | "log",
182 | "mime",
183 | "once_cell",
184 | "pin-project-lite",
185 | "regex",
186 | "serde",
187 | "serde_json",
188 | "serde_urlencoded",
189 | "smallvec",
190 | "socket2",
191 | "time",
192 | "url",
193 | ]
194 |
195 | [[package]]
196 | name = "actix-web-codegen"
197 | version = "4.2.0"
198 | source = "registry+https://github.com/rust-lang/crates.io-index"
199 | checksum = "2262160a7ae29e3415554a3f1fc04c764b1540c116aa524683208078b7a75bc9"
200 | dependencies = [
201 | "actix-router",
202 | "proc-macro2",
203 | "quote",
204 | "syn",
205 | ]
206 |
207 | [[package]]
208 | name = "actix-web-prom"
209 | version = "0.6.0"
210 | source = "registry+https://github.com/rust-lang/crates.io-index"
211 | checksum = "9df3127d20a5d01c9fc9aceb969a38d31a6767e1b48a54d55a8f56c769a84923"
212 | dependencies = [
213 | "actix-web",
214 | "futures-core",
215 | "pin-project-lite",
216 | "prometheus",
217 | ]
218 |
219 | [[package]]
220 | name = "adler"
221 | version = "1.0.2"
222 | source = "registry+https://github.com/rust-lang/crates.io-index"
223 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
224 |
225 | [[package]]
226 | name = "ahash"
227 | version = "0.7.6"
228 | source = "registry+https://github.com/rust-lang/crates.io-index"
229 | checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
230 | dependencies = [
231 | "getrandom",
232 | "once_cell",
233 | "version_check",
234 | ]
235 |
236 | [[package]]
237 | name = "ahash"
238 | version = "0.8.3"
239 | source = "registry+https://github.com/rust-lang/crates.io-index"
240 | checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
241 | dependencies = [
242 | "cfg-if",
243 | "getrandom",
244 | "once_cell",
245 | "version_check",
246 | ]
247 |
248 | [[package]]
249 | name = "aho-corasick"
250 | version = "0.7.20"
251 | source = "registry+https://github.com/rust-lang/crates.io-index"
252 | checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
253 | dependencies = [
254 | "memchr",
255 | ]
256 |
257 | [[package]]
258 | name = "alloc-no-stdlib"
259 | version = "2.0.4"
260 | source = "registry+https://github.com/rust-lang/crates.io-index"
261 | checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
262 |
263 | [[package]]
264 | name = "alloc-stdlib"
265 | version = "0.2.2"
266 | source = "registry+https://github.com/rust-lang/crates.io-index"
267 | checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
268 | dependencies = [
269 | "alloc-no-stdlib",
270 | ]
271 |
272 | [[package]]
273 | name = "anyhow"
274 | version = "1.0.69"
275 | source = "registry+https://github.com/rust-lang/crates.io-index"
276 | checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
277 |
278 | [[package]]
279 | name = "array_tool"
280 | version = "1.0.3"
281 | source = "registry+https://github.com/rust-lang/crates.io-index"
282 | checksum = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271"
283 |
284 | [[package]]
285 | name = "async-trait"
286 | version = "0.1.66"
287 | source = "registry+https://github.com/rust-lang/crates.io-index"
288 | checksum = "b84f9ebcc6c1f5b8cb160f6990096a5c127f423fcb6e1ccc46c370cbdfb75dfc"
289 | dependencies = [
290 | "proc-macro2",
291 | "quote",
292 | "syn",
293 | ]
294 |
295 | [[package]]
296 | name = "async_once"
297 | version = "0.2.6"
298 | source = "registry+https://github.com/rust-lang/crates.io-index"
299 | checksum = "2ce4f10ea3abcd6617873bae9f91d1c5332b4a778bd9ce34d0cd517474c1de82"
300 |
301 | [[package]]
302 | name = "atty"
303 | version = "0.2.14"
304 | source = "registry+https://github.com/rust-lang/crates.io-index"
305 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
306 | dependencies = [
307 | "hermit-abi 0.1.19",
308 | "libc",
309 | "winapi",
310 | ]
311 |
312 | [[package]]
313 | name = "autocfg"
314 | version = "1.1.0"
315 | source = "registry+https://github.com/rust-lang/crates.io-index"
316 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
317 |
318 | [[package]]
319 | name = "awc"
320 | version = "3.1.1"
321 | source = "registry+https://github.com/rust-lang/crates.io-index"
322 | checksum = "87ef547a81796eb2dfe9b345aba34c2e08391a0502493711395b36dd64052b69"
323 | dependencies = [
324 | "actix-codec",
325 | "actix-http",
326 | "actix-rt",
327 | "actix-service",
328 | "actix-tls",
329 | "actix-utils",
330 | "ahash 0.7.6",
331 | "base64 0.21.0",
332 | "bytes",
333 | "cfg-if",
334 | "cookie",
335 | "derive_more",
336 | "futures-core",
337 | "futures-util",
338 | "h2",
339 | "http",
340 | "itoa",
341 | "log",
342 | "mime",
343 | "percent-encoding",
344 | "pin-project-lite",
345 | "rand",
346 | "rustls",
347 | "serde",
348 | "serde_json",
349 | "serde_urlencoded",
350 | "tokio",
351 | ]
352 |
353 | [[package]]
354 | name = "base64"
355 | version = "0.13.1"
356 | source = "registry+https://github.com/rust-lang/crates.io-index"
357 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
358 |
359 | [[package]]
360 | name = "base64"
361 | version = "0.21.0"
362 | source = "registry+https://github.com/rust-lang/crates.io-index"
363 | checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
364 |
365 | [[package]]
366 | name = "bitflags"
367 | version = "1.3.2"
368 | source = "registry+https://github.com/rust-lang/crates.io-index"
369 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
370 |
371 | [[package]]
372 | name = "block-buffer"
373 | version = "0.10.4"
374 | source = "registry+https://github.com/rust-lang/crates.io-index"
375 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
376 | dependencies = [
377 | "generic-array",
378 | ]
379 |
380 | [[package]]
381 | name = "brotli"
382 | version = "3.3.4"
383 | source = "registry+https://github.com/rust-lang/crates.io-index"
384 | checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68"
385 | dependencies = [
386 | "alloc-no-stdlib",
387 | "alloc-stdlib",
388 | "brotli-decompressor",
389 | ]
390 |
391 | [[package]]
392 | name = "brotli-decompressor"
393 | version = "2.3.4"
394 | source = "registry+https://github.com/rust-lang/crates.io-index"
395 | checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744"
396 | dependencies = [
397 | "alloc-no-stdlib",
398 | "alloc-stdlib",
399 | ]
400 |
401 | [[package]]
402 | name = "bumpalo"
403 | version = "3.12.0"
404 | source = "registry+https://github.com/rust-lang/crates.io-index"
405 | checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
406 |
407 | [[package]]
408 | name = "bytes"
409 | version = "1.4.0"
410 | source = "registry+https://github.com/rust-lang/crates.io-index"
411 | checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
412 |
413 | [[package]]
414 | name = "bytestring"
415 | version = "1.3.0"
416 | source = "registry+https://github.com/rust-lang/crates.io-index"
417 | checksum = "238e4886760d98c4f899360c834fa93e62cf7f721ac3c2da375cbdf4b8679aae"
418 | dependencies = [
419 | "bytes",
420 | ]
421 |
422 | [[package]]
423 | name = "cached"
424 | version = "0.42.0"
425 | source = "registry+https://github.com/rust-lang/crates.io-index"
426 | checksum = "5e5877db5d1af7fae60d06b5db9430b68056a69b3582a0be8e3691e87654aeb6"
427 | dependencies = [
428 | "async-trait",
429 | "async_once",
430 | "cached_proc_macro",
431 | "cached_proc_macro_types",
432 | "futures",
433 | "hashbrown 0.13.2",
434 | "instant",
435 | "lazy_static",
436 | "once_cell",
437 | "thiserror",
438 | "tokio",
439 | ]
440 |
441 | [[package]]
442 | name = "cached_proc_macro"
443 | version = "0.16.0"
444 | source = "registry+https://github.com/rust-lang/crates.io-index"
445 | checksum = "e10ca87c81aaa3a949dbbe2b5e6c2c45dbc94ba4897e45ea31ff9ec5087be3dc"
446 | dependencies = [
447 | "cached_proc_macro_types",
448 | "darling",
449 | "proc-macro2",
450 | "quote",
451 | "syn",
452 | ]
453 |
454 | [[package]]
455 | name = "cached_proc_macro_types"
456 | version = "0.1.0"
457 | source = "registry+https://github.com/rust-lang/crates.io-index"
458 | checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663"
459 |
460 | [[package]]
461 | name = "cc"
462 | version = "1.0.79"
463 | source = "registry+https://github.com/rust-lang/crates.io-index"
464 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
465 | dependencies = [
466 | "jobserver",
467 | ]
468 |
469 | [[package]]
470 | name = "cfg-if"
471 | version = "1.0.0"
472 | source = "registry+https://github.com/rust-lang/crates.io-index"
473 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
474 |
475 | [[package]]
476 | name = "config"
477 | version = "0.13.3"
478 | source = "registry+https://github.com/rust-lang/crates.io-index"
479 | checksum = "d379af7f68bfc21714c6c7dea883544201741d2ce8274bb12fa54f89507f52a7"
480 | dependencies = [
481 | "async-trait",
482 | "json5",
483 | "lazy_static",
484 | "nom",
485 | "pathdiff",
486 | "ron",
487 | "rust-ini",
488 | "serde",
489 | "serde_json",
490 | "toml",
491 | "yaml-rust",
492 | ]
493 |
494 | [[package]]
495 | name = "const_format"
496 | version = "0.2.30"
497 | source = "registry+https://github.com/rust-lang/crates.io-index"
498 | checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e"
499 | dependencies = [
500 | "const_format_proc_macros",
501 | ]
502 |
503 | [[package]]
504 | name = "const_format_proc_macros"
505 | version = "0.2.29"
506 | source = "registry+https://github.com/rust-lang/crates.io-index"
507 | checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650"
508 | dependencies = [
509 | "proc-macro2",
510 | "quote",
511 | "unicode-xid",
512 | ]
513 |
514 | [[package]]
515 | name = "convert_case"
516 | version = "0.4.0"
517 | source = "registry+https://github.com/rust-lang/crates.io-index"
518 | checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
519 |
520 | [[package]]
521 | name = "cookie"
522 | version = "0.16.2"
523 | source = "registry+https://github.com/rust-lang/crates.io-index"
524 | checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
525 | dependencies = [
526 | "percent-encoding",
527 | "time",
528 | "version_check",
529 | ]
530 |
531 | [[package]]
532 | name = "cpufeatures"
533 | version = "0.2.5"
534 | source = "registry+https://github.com/rust-lang/crates.io-index"
535 | checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
536 | dependencies = [
537 | "libc",
538 | ]
539 |
540 | [[package]]
541 | name = "crc32fast"
542 | version = "1.3.2"
543 | source = "registry+https://github.com/rust-lang/crates.io-index"
544 | checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
545 | dependencies = [
546 | "cfg-if",
547 | ]
548 |
549 | [[package]]
550 | name = "crypto-common"
551 | version = "0.1.6"
552 | source = "registry+https://github.com/rust-lang/crates.io-index"
553 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
554 | dependencies = [
555 | "generic-array",
556 | "typenum",
557 | ]
558 |
559 | [[package]]
560 | name = "ctor"
561 | version = "0.1.26"
562 | source = "registry+https://github.com/rust-lang/crates.io-index"
563 | checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
564 | dependencies = [
565 | "quote",
566 | "syn",
567 | ]
568 |
569 | [[package]]
570 | name = "darling"
571 | version = "0.14.3"
572 | source = "registry+https://github.com/rust-lang/crates.io-index"
573 | checksum = "c0808e1bd8671fb44a113a14e13497557533369847788fa2ae912b6ebfce9fa8"
574 | dependencies = [
575 | "darling_core",
576 | "darling_macro",
577 | ]
578 |
579 | [[package]]
580 | name = "darling_core"
581 | version = "0.14.3"
582 | source = "registry+https://github.com/rust-lang/crates.io-index"
583 | checksum = "001d80444f28e193f30c2f293455da62dcf9a6b29918a4253152ae2b1de592cb"
584 | dependencies = [
585 | "fnv",
586 | "ident_case",
587 | "proc-macro2",
588 | "quote",
589 | "strsim",
590 | "syn",
591 | ]
592 |
593 | [[package]]
594 | name = "darling_macro"
595 | version = "0.14.3"
596 | source = "registry+https://github.com/rust-lang/crates.io-index"
597 | checksum = "b36230598a2d5de7ec1c6f51f72d8a99a9208daff41de2084d06e3fd3ea56685"
598 | dependencies = [
599 | "darling_core",
600 | "quote",
601 | "syn",
602 | ]
603 |
604 | [[package]]
605 | name = "derive_more"
606 | version = "0.99.17"
607 | source = "registry+https://github.com/rust-lang/crates.io-index"
608 | checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
609 | dependencies = [
610 | "convert_case",
611 | "proc-macro2",
612 | "quote",
613 | "rustc_version",
614 | "syn",
615 | ]
616 |
617 | [[package]]
618 | name = "digest"
619 | version = "0.10.6"
620 | source = "registry+https://github.com/rust-lang/crates.io-index"
621 | checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
622 | dependencies = [
623 | "block-buffer",
624 | "crypto-common",
625 | ]
626 |
627 | [[package]]
628 | name = "dlv-list"
629 | version = "0.3.0"
630 | source = "registry+https://github.com/rust-lang/crates.io-index"
631 | checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
632 |
633 | [[package]]
634 | name = "docker-image-reference"
635 | version = "0.1.0"
636 | source = "git+https://github.com/PeterGrace/docker-image-reference.git#d2f97edef269b20548664cf123057b90f0557d2e"
637 | dependencies = [
638 | "anyhow",
639 | "const_format",
640 | "lazy_static",
641 | "log",
642 | "regex",
643 | ]
644 |
645 | [[package]]
646 | name = "encoding_rs"
647 | version = "0.8.32"
648 | source = "registry+https://github.com/rust-lang/crates.io-index"
649 | checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394"
650 | dependencies = [
651 | "cfg-if",
652 | ]
653 |
654 | [[package]]
655 | name = "env_logger"
656 | version = "0.7.1"
657 | source = "registry+https://github.com/rust-lang/crates.io-index"
658 | checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
659 | dependencies = [
660 | "atty",
661 | "humantime",
662 | "log",
663 | "regex",
664 | "termcolor",
665 | ]
666 |
667 | [[package]]
668 | name = "flate2"
669 | version = "1.0.25"
670 | source = "registry+https://github.com/rust-lang/crates.io-index"
671 | checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
672 | dependencies = [
673 | "crc32fast",
674 | "miniz_oxide",
675 | ]
676 |
677 | [[package]]
678 | name = "fnv"
679 | version = "1.0.7"
680 | source = "registry+https://github.com/rust-lang/crates.io-index"
681 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
682 |
683 | [[package]]
684 | name = "form_urlencoded"
685 | version = "1.1.0"
686 | source = "registry+https://github.com/rust-lang/crates.io-index"
687 | checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
688 | dependencies = [
689 | "percent-encoding",
690 | ]
691 |
692 | [[package]]
693 | name = "futures"
694 | version = "0.3.26"
695 | source = "registry+https://github.com/rust-lang/crates.io-index"
696 | checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84"
697 | dependencies = [
698 | "futures-channel",
699 | "futures-core",
700 | "futures-io",
701 | "futures-sink",
702 | "futures-task",
703 | "futures-util",
704 | ]
705 |
706 | [[package]]
707 | name = "futures-channel"
708 | version = "0.3.26"
709 | source = "registry+https://github.com/rust-lang/crates.io-index"
710 | checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5"
711 | dependencies = [
712 | "futures-core",
713 | "futures-sink",
714 | ]
715 |
716 | [[package]]
717 | name = "futures-core"
718 | version = "0.3.26"
719 | source = "registry+https://github.com/rust-lang/crates.io-index"
720 | checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
721 |
722 | [[package]]
723 | name = "futures-io"
724 | version = "0.3.26"
725 | source = "registry+https://github.com/rust-lang/crates.io-index"
726 | checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
727 |
728 | [[package]]
729 | name = "futures-sink"
730 | version = "0.3.26"
731 | source = "registry+https://github.com/rust-lang/crates.io-index"
732 | checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364"
733 |
734 | [[package]]
735 | name = "futures-task"
736 | version = "0.3.26"
737 | source = "registry+https://github.com/rust-lang/crates.io-index"
738 | checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366"
739 |
740 | [[package]]
741 | name = "futures-util"
742 | version = "0.3.26"
743 | source = "registry+https://github.com/rust-lang/crates.io-index"
744 | checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
745 | dependencies = [
746 | "futures-core",
747 | "futures-sink",
748 | "futures-task",
749 | "pin-project-lite",
750 | "pin-utils",
751 | ]
752 |
753 | [[package]]
754 | name = "generic-array"
755 | version = "0.14.6"
756 | source = "registry+https://github.com/rust-lang/crates.io-index"
757 | checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
758 | dependencies = [
759 | "typenum",
760 | "version_check",
761 | ]
762 |
763 | [[package]]
764 | name = "getrandom"
765 | version = "0.2.8"
766 | source = "registry+https://github.com/rust-lang/crates.io-index"
767 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
768 | dependencies = [
769 | "cfg-if",
770 | "libc",
771 | "wasi",
772 | ]
773 |
774 | [[package]]
775 | name = "h2"
776 | version = "0.3.16"
777 | source = "registry+https://github.com/rust-lang/crates.io-index"
778 | checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d"
779 | dependencies = [
780 | "bytes",
781 | "fnv",
782 | "futures-core",
783 | "futures-sink",
784 | "futures-util",
785 | "http",
786 | "indexmap",
787 | "slab",
788 | "tokio",
789 | "tokio-util",
790 | "tracing",
791 | ]
792 |
793 | [[package]]
794 | name = "hashbrown"
795 | version = "0.12.3"
796 | source = "registry+https://github.com/rust-lang/crates.io-index"
797 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
798 | dependencies = [
799 | "ahash 0.7.6",
800 | ]
801 |
802 | [[package]]
803 | name = "hashbrown"
804 | version = "0.13.2"
805 | source = "registry+https://github.com/rust-lang/crates.io-index"
806 | checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
807 |
808 | [[package]]
809 | name = "heck"
810 | version = "0.4.1"
811 | source = "registry+https://github.com/rust-lang/crates.io-index"
812 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
813 |
814 | [[package]]
815 | name = "hermit-abi"
816 | version = "0.1.19"
817 | source = "registry+https://github.com/rust-lang/crates.io-index"
818 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
819 | dependencies = [
820 | "libc",
821 | ]
822 |
823 | [[package]]
824 | name = "hermit-abi"
825 | version = "0.2.6"
826 | source = "registry+https://github.com/rust-lang/crates.io-index"
827 | checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
828 | dependencies = [
829 | "libc",
830 | ]
831 |
832 | [[package]]
833 | name = "http"
834 | version = "0.2.9"
835 | source = "registry+https://github.com/rust-lang/crates.io-index"
836 | checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
837 | dependencies = [
838 | "bytes",
839 | "fnv",
840 | "itoa",
841 | ]
842 |
843 | [[package]]
844 | name = "httparse"
845 | version = "1.8.0"
846 | source = "registry+https://github.com/rust-lang/crates.io-index"
847 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
848 |
849 | [[package]]
850 | name = "httpdate"
851 | version = "1.0.2"
852 | source = "registry+https://github.com/rust-lang/crates.io-index"
853 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
854 |
855 | [[package]]
856 | name = "humantime"
857 | version = "1.3.0"
858 | source = "registry+https://github.com/rust-lang/crates.io-index"
859 | checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
860 | dependencies = [
861 | "quick-error",
862 | ]
863 |
864 | [[package]]
865 | name = "ident_case"
866 | version = "1.0.1"
867 | source = "registry+https://github.com/rust-lang/crates.io-index"
868 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
869 |
870 | [[package]]
871 | name = "idna"
872 | version = "0.3.0"
873 | source = "registry+https://github.com/rust-lang/crates.io-index"
874 | checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
875 | dependencies = [
876 | "unicode-bidi",
877 | "unicode-normalization",
878 | ]
879 |
880 | [[package]]
881 | name = "indexmap"
882 | version = "1.9.2"
883 | source = "registry+https://github.com/rust-lang/crates.io-index"
884 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
885 | dependencies = [
886 | "autocfg",
887 | "hashbrown 0.12.3",
888 | ]
889 |
890 | [[package]]
891 | name = "instant"
892 | version = "0.1.12"
893 | source = "registry+https://github.com/rust-lang/crates.io-index"
894 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
895 | dependencies = [
896 | "cfg-if",
897 | ]
898 |
899 | [[package]]
900 | name = "itoa"
901 | version = "1.0.6"
902 | source = "registry+https://github.com/rust-lang/crates.io-index"
903 | checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
904 |
905 | [[package]]
906 | name = "jobserver"
907 | version = "0.1.26"
908 | source = "registry+https://github.com/rust-lang/crates.io-index"
909 | checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
910 | dependencies = [
911 | "libc",
912 | ]
913 |
914 | [[package]]
915 | name = "js-sys"
916 | version = "0.3.61"
917 | source = "registry+https://github.com/rust-lang/crates.io-index"
918 | checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
919 | dependencies = [
920 | "wasm-bindgen",
921 | ]
922 |
923 | [[package]]
924 | name = "json5"
925 | version = "0.4.1"
926 | source = "registry+https://github.com/rust-lang/crates.io-index"
927 | checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1"
928 | dependencies = [
929 | "pest",
930 | "pest_derive",
931 | "serde",
932 | ]
933 |
934 | [[package]]
935 | name = "language-tags"
936 | version = "0.3.2"
937 | source = "registry+https://github.com/rust-lang/crates.io-index"
938 | checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
939 |
940 | [[package]]
941 | name = "lazy_static"
942 | version = "1.4.0"
943 | source = "registry+https://github.com/rust-lang/crates.io-index"
944 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
945 |
946 | [[package]]
947 | name = "libc"
948 | version = "0.2.139"
949 | source = "registry+https://github.com/rust-lang/crates.io-index"
950 | checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
951 |
952 | [[package]]
953 | name = "linked-hash-map"
954 | version = "0.5.6"
955 | source = "registry+https://github.com/rust-lang/crates.io-index"
956 | checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
957 |
958 | [[package]]
959 | name = "local-channel"
960 | version = "0.1.3"
961 | source = "registry+https://github.com/rust-lang/crates.io-index"
962 | checksum = "7f303ec0e94c6c54447f84f3b0ef7af769858a9c4ef56ef2a986d3dcd4c3fc9c"
963 | dependencies = [
964 | "futures-core",
965 | "futures-sink",
966 | "futures-util",
967 | "local-waker",
968 | ]
969 |
970 | [[package]]
971 | name = "local-waker"
972 | version = "0.1.3"
973 | source = "registry+https://github.com/rust-lang/crates.io-index"
974 | checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1"
975 |
976 | [[package]]
977 | name = "lock_api"
978 | version = "0.4.9"
979 | source = "registry+https://github.com/rust-lang/crates.io-index"
980 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
981 | dependencies = [
982 | "autocfg",
983 | "scopeguard",
984 | ]
985 |
986 | [[package]]
987 | name = "log"
988 | version = "0.4.17"
989 | source = "registry+https://github.com/rust-lang/crates.io-index"
990 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
991 | dependencies = [
992 | "cfg-if",
993 | ]
994 |
995 | [[package]]
996 | name = "memchr"
997 | version = "2.5.0"
998 | source = "registry+https://github.com/rust-lang/crates.io-index"
999 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
1000 |
1001 | [[package]]
1002 | name = "mime"
1003 | version = "0.3.16"
1004 | source = "registry+https://github.com/rust-lang/crates.io-index"
1005 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
1006 |
1007 | [[package]]
1008 | name = "minimal-lexical"
1009 | version = "0.2.1"
1010 | source = "registry+https://github.com/rust-lang/crates.io-index"
1011 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
1012 |
1013 | [[package]]
1014 | name = "miniz_oxide"
1015 | version = "0.6.2"
1016 | source = "registry+https://github.com/rust-lang/crates.io-index"
1017 | checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
1018 | dependencies = [
1019 | "adler",
1020 | ]
1021 |
1022 | [[package]]
1023 | name = "mio"
1024 | version = "0.8.6"
1025 | source = "registry+https://github.com/rust-lang/crates.io-index"
1026 | checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
1027 | dependencies = [
1028 | "libc",
1029 | "log",
1030 | "wasi",
1031 | "windows-sys",
1032 | ]
1033 |
1034 | [[package]]
1035 | name = "nom"
1036 | version = "7.1.3"
1037 | source = "registry+https://github.com/rust-lang/crates.io-index"
1038 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
1039 | dependencies = [
1040 | "memchr",
1041 | "minimal-lexical",
1042 | ]
1043 |
1044 | [[package]]
1045 | name = "num_cpus"
1046 | version = "1.15.0"
1047 | source = "registry+https://github.com/rust-lang/crates.io-index"
1048 | checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
1049 | dependencies = [
1050 | "hermit-abi 0.2.6",
1051 | "libc",
1052 | ]
1053 |
1054 | [[package]]
1055 | name = "once_cell"
1056 | version = "1.17.1"
1057 | source = "registry+https://github.com/rust-lang/crates.io-index"
1058 | checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
1059 |
1060 | [[package]]
1061 | name = "ordered-multimap"
1062 | version = "0.4.3"
1063 | source = "registry+https://github.com/rust-lang/crates.io-index"
1064 | checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a"
1065 | dependencies = [
1066 | "dlv-list",
1067 | "hashbrown 0.12.3",
1068 | ]
1069 |
1070 | [[package]]
1071 | name = "parking_lot"
1072 | version = "0.12.1"
1073 | source = "registry+https://github.com/rust-lang/crates.io-index"
1074 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
1075 | dependencies = [
1076 | "lock_api",
1077 | "parking_lot_core",
1078 | ]
1079 |
1080 | [[package]]
1081 | name = "parking_lot_core"
1082 | version = "0.9.7"
1083 | source = "registry+https://github.com/rust-lang/crates.io-index"
1084 | checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
1085 | dependencies = [
1086 | "cfg-if",
1087 | "libc",
1088 | "redox_syscall",
1089 | "smallvec",
1090 | "windows-sys",
1091 | ]
1092 |
1093 | [[package]]
1094 | name = "paste"
1095 | version = "1.0.12"
1096 | source = "registry+https://github.com/rust-lang/crates.io-index"
1097 | checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
1098 |
1099 | [[package]]
1100 | name = "pathdiff"
1101 | version = "0.2.1"
1102 | source = "registry+https://github.com/rust-lang/crates.io-index"
1103 | checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
1104 |
1105 | [[package]]
1106 | name = "percent-encoding"
1107 | version = "2.2.0"
1108 | source = "registry+https://github.com/rust-lang/crates.io-index"
1109 | checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
1110 |
1111 | [[package]]
1112 | name = "pest"
1113 | version = "2.5.6"
1114 | source = "registry+https://github.com/rust-lang/crates.io-index"
1115 | checksum = "8cbd939b234e95d72bc393d51788aec68aeeb5d51e748ca08ff3aad58cb722f7"
1116 | dependencies = [
1117 | "thiserror",
1118 | "ucd-trie",
1119 | ]
1120 |
1121 | [[package]]
1122 | name = "pest_derive"
1123 | version = "2.5.6"
1124 | source = "registry+https://github.com/rust-lang/crates.io-index"
1125 | checksum = "a81186863f3d0a27340815be8f2078dd8050b14cd71913db9fbda795e5f707d7"
1126 | dependencies = [
1127 | "pest",
1128 | "pest_generator",
1129 | ]
1130 |
1131 | [[package]]
1132 | name = "pest_generator"
1133 | version = "2.5.6"
1134 | source = "registry+https://github.com/rust-lang/crates.io-index"
1135 | checksum = "75a1ef20bf3193c15ac345acb32e26b3dc3223aff4d77ae4fc5359567683796b"
1136 | dependencies = [
1137 | "pest",
1138 | "pest_meta",
1139 | "proc-macro2",
1140 | "quote",
1141 | "syn",
1142 | ]
1143 |
1144 | [[package]]
1145 | name = "pest_meta"
1146 | version = "2.5.6"
1147 | source = "registry+https://github.com/rust-lang/crates.io-index"
1148 | checksum = "5e3b284b1f13a20dc5ebc90aff59a51b8d7137c221131b52a7260c08cbc1cc80"
1149 | dependencies = [
1150 | "once_cell",
1151 | "pest",
1152 | "sha2",
1153 | ]
1154 |
1155 | [[package]]
1156 | name = "pin-project-lite"
1157 | version = "0.2.9"
1158 | source = "registry+https://github.com/rust-lang/crates.io-index"
1159 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
1160 |
1161 | [[package]]
1162 | name = "pin-utils"
1163 | version = "0.1.0"
1164 | source = "registry+https://github.com/rust-lang/crates.io-index"
1165 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
1166 |
1167 | [[package]]
1168 | name = "pkg-config"
1169 | version = "0.3.26"
1170 | source = "registry+https://github.com/rust-lang/crates.io-index"
1171 | checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
1172 |
1173 | [[package]]
1174 | name = "ppv-lite86"
1175 | version = "0.2.17"
1176 | source = "registry+https://github.com/rust-lang/crates.io-index"
1177 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
1178 |
1179 | [[package]]
1180 | name = "pretty_env_logger"
1181 | version = "0.4.0"
1182 | source = "registry+https://github.com/rust-lang/crates.io-index"
1183 | checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
1184 | dependencies = [
1185 | "env_logger",
1186 | "log",
1187 | ]
1188 |
1189 | [[package]]
1190 | name = "proc-macro2"
1191 | version = "1.0.51"
1192 | source = "registry+https://github.com/rust-lang/crates.io-index"
1193 | checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
1194 | dependencies = [
1195 | "unicode-ident",
1196 | ]
1197 |
1198 | [[package]]
1199 | name = "prometheus"
1200 | version = "0.13.3"
1201 | source = "registry+https://github.com/rust-lang/crates.io-index"
1202 | checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c"
1203 | dependencies = [
1204 | "cfg-if",
1205 | "fnv",
1206 | "lazy_static",
1207 | "memchr",
1208 | "parking_lot",
1209 | "protobuf",
1210 | "thiserror",
1211 | ]
1212 |
1213 | [[package]]
1214 | name = "protobuf"
1215 | version = "2.28.0"
1216 | source = "registry+https://github.com/rust-lang/crates.io-index"
1217 | checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94"
1218 |
1219 | [[package]]
1220 | name = "quick-error"
1221 | version = "1.2.3"
1222 | source = "registry+https://github.com/rust-lang/crates.io-index"
1223 | checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
1224 |
1225 | [[package]]
1226 | name = "quote"
1227 | version = "1.0.23"
1228 | source = "registry+https://github.com/rust-lang/crates.io-index"
1229 | checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
1230 | dependencies = [
1231 | "proc-macro2",
1232 | ]
1233 |
1234 | [[package]]
1235 | name = "rand"
1236 | version = "0.8.5"
1237 | source = "registry+https://github.com/rust-lang/crates.io-index"
1238 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
1239 | dependencies = [
1240 | "libc",
1241 | "rand_chacha",
1242 | "rand_core",
1243 | ]
1244 |
1245 | [[package]]
1246 | name = "rand_chacha"
1247 | version = "0.3.1"
1248 | source = "registry+https://github.com/rust-lang/crates.io-index"
1249 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
1250 | dependencies = [
1251 | "ppv-lite86",
1252 | "rand_core",
1253 | ]
1254 |
1255 | [[package]]
1256 | name = "rand_core"
1257 | version = "0.6.4"
1258 | source = "registry+https://github.com/rust-lang/crates.io-index"
1259 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
1260 | dependencies = [
1261 | "getrandom",
1262 | ]
1263 |
1264 | [[package]]
1265 | name = "redox_syscall"
1266 | version = "0.2.16"
1267 | source = "registry+https://github.com/rust-lang/crates.io-index"
1268 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
1269 | dependencies = [
1270 | "bitflags",
1271 | ]
1272 |
1273 | [[package]]
1274 | name = "regex"
1275 | version = "1.7.1"
1276 | source = "registry+https://github.com/rust-lang/crates.io-index"
1277 | checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
1278 | dependencies = [
1279 | "aho-corasick",
1280 | "memchr",
1281 | "regex-syntax",
1282 | ]
1283 |
1284 | [[package]]
1285 | name = "regex-syntax"
1286 | version = "0.6.28"
1287 | source = "registry+https://github.com/rust-lang/crates.io-index"
1288 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
1289 |
1290 | [[package]]
1291 | name = "ring"
1292 | version = "0.16.20"
1293 | source = "registry+https://github.com/rust-lang/crates.io-index"
1294 | checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
1295 | dependencies = [
1296 | "cc",
1297 | "libc",
1298 | "once_cell",
1299 | "spin",
1300 | "untrusted",
1301 | "web-sys",
1302 | "winapi",
1303 | ]
1304 |
1305 | [[package]]
1306 | name = "ron"
1307 | version = "0.7.1"
1308 | source = "registry+https://github.com/rust-lang/crates.io-index"
1309 | checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
1310 | dependencies = [
1311 | "base64 0.13.1",
1312 | "bitflags",
1313 | "serde",
1314 | ]
1315 |
1316 | [[package]]
1317 | name = "rust-ini"
1318 | version = "0.18.0"
1319 | source = "registry+https://github.com/rust-lang/crates.io-index"
1320 | checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df"
1321 | dependencies = [
1322 | "cfg-if",
1323 | "ordered-multimap",
1324 | ]
1325 |
1326 | [[package]]
1327 | name = "rustc_version"
1328 | version = "0.4.0"
1329 | source = "registry+https://github.com/rust-lang/crates.io-index"
1330 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
1331 | dependencies = [
1332 | "semver",
1333 | ]
1334 |
1335 | [[package]]
1336 | name = "rustls"
1337 | version = "0.20.8"
1338 | source = "registry+https://github.com/rust-lang/crates.io-index"
1339 | checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
1340 | dependencies = [
1341 | "log",
1342 | "ring",
1343 | "sct",
1344 | "webpki",
1345 | ]
1346 |
1347 | [[package]]
1348 | name = "rustls-pemfile"
1349 | version = "1.0.2"
1350 | source = "registry+https://github.com/rust-lang/crates.io-index"
1351 | checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
1352 | dependencies = [
1353 | "base64 0.21.0",
1354 | ]
1355 |
1356 | [[package]]
1357 | name = "rustversion"
1358 | version = "1.0.12"
1359 | source = "registry+https://github.com/rust-lang/crates.io-index"
1360 | checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
1361 |
1362 | [[package]]
1363 | name = "ryu"
1364 | version = "1.0.13"
1365 | source = "registry+https://github.com/rust-lang/crates.io-index"
1366 | checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
1367 |
1368 | [[package]]
1369 | name = "scopeguard"
1370 | version = "1.1.0"
1371 | source = "registry+https://github.com/rust-lang/crates.io-index"
1372 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
1373 |
1374 | [[package]]
1375 | name = "sct"
1376 | version = "0.7.0"
1377 | source = "registry+https://github.com/rust-lang/crates.io-index"
1378 | checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
1379 | dependencies = [
1380 | "ring",
1381 | "untrusted",
1382 | ]
1383 |
1384 | [[package]]
1385 | name = "semver"
1386 | version = "1.0.16"
1387 | source = "registry+https://github.com/rust-lang/crates.io-index"
1388 | checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
1389 |
1390 | [[package]]
1391 | name = "serde"
1392 | version = "1.0.154"
1393 | source = "registry+https://github.com/rust-lang/crates.io-index"
1394 | checksum = "8cdd151213925e7f1ab45a9bbfb129316bd00799784b174b7cc7bcd16961c49e"
1395 | dependencies = [
1396 | "serde_derive",
1397 | ]
1398 |
1399 | [[package]]
1400 | name = "serde_derive"
1401 | version = "1.0.154"
1402 | source = "registry+https://github.com/rust-lang/crates.io-index"
1403 | checksum = "4fc80d722935453bcafdc2c9a73cd6fac4dc1938f0346035d84bf99fa9e33217"
1404 | dependencies = [
1405 | "proc-macro2",
1406 | "quote",
1407 | "syn",
1408 | ]
1409 |
1410 | [[package]]
1411 | name = "serde_json"
1412 | version = "1.0.94"
1413 | source = "registry+https://github.com/rust-lang/crates.io-index"
1414 | checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea"
1415 | dependencies = [
1416 | "itoa",
1417 | "ryu",
1418 | "serde",
1419 | ]
1420 |
1421 | [[package]]
1422 | name = "serde_urlencoded"
1423 | version = "0.7.1"
1424 | source = "registry+https://github.com/rust-lang/crates.io-index"
1425 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
1426 | dependencies = [
1427 | "form_urlencoded",
1428 | "itoa",
1429 | "ryu",
1430 | "serde",
1431 | ]
1432 |
1433 | [[package]]
1434 | name = "sha1"
1435 | version = "0.10.5"
1436 | source = "registry+https://github.com/rust-lang/crates.io-index"
1437 | checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
1438 | dependencies = [
1439 | "cfg-if",
1440 | "cpufeatures",
1441 | "digest",
1442 | ]
1443 |
1444 | [[package]]
1445 | name = "sha2"
1446 | version = "0.10.6"
1447 | source = "registry+https://github.com/rust-lang/crates.io-index"
1448 | checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
1449 | dependencies = [
1450 | "cfg-if",
1451 | "cpufeatures",
1452 | "digest",
1453 | ]
1454 |
1455 | [[package]]
1456 | name = "signal-hook-registry"
1457 | version = "1.4.1"
1458 | source = "registry+https://github.com/rust-lang/crates.io-index"
1459 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
1460 | dependencies = [
1461 | "libc",
1462 | ]
1463 |
1464 | [[package]]
1465 | name = "slab"
1466 | version = "0.4.8"
1467 | source = "registry+https://github.com/rust-lang/crates.io-index"
1468 | checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
1469 | dependencies = [
1470 | "autocfg",
1471 | ]
1472 |
1473 | [[package]]
1474 | name = "smallvec"
1475 | version = "1.10.0"
1476 | source = "registry+https://github.com/rust-lang/crates.io-index"
1477 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
1478 |
1479 | [[package]]
1480 | name = "socket2"
1481 | version = "0.4.9"
1482 | source = "registry+https://github.com/rust-lang/crates.io-index"
1483 | checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
1484 | dependencies = [
1485 | "libc",
1486 | "winapi",
1487 | ]
1488 |
1489 | [[package]]
1490 | name = "spin"
1491 | version = "0.5.2"
1492 | source = "registry+https://github.com/rust-lang/crates.io-index"
1493 | checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
1494 |
1495 | [[package]]
1496 | name = "strsim"
1497 | version = "0.10.0"
1498 | source = "registry+https://github.com/rust-lang/crates.io-index"
1499 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
1500 |
1501 | [[package]]
1502 | name = "strum"
1503 | version = "0.24.1"
1504 | source = "registry+https://github.com/rust-lang/crates.io-index"
1505 | checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
1506 |
1507 | [[package]]
1508 | name = "strum_macros"
1509 | version = "0.24.3"
1510 | source = "registry+https://github.com/rust-lang/crates.io-index"
1511 | checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
1512 | dependencies = [
1513 | "heck",
1514 | "proc-macro2",
1515 | "quote",
1516 | "rustversion",
1517 | "syn",
1518 | ]
1519 |
1520 | [[package]]
1521 | name = "syn"
1522 | version = "1.0.109"
1523 | source = "registry+https://github.com/rust-lang/crates.io-index"
1524 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
1525 | dependencies = [
1526 | "proc-macro2",
1527 | "quote",
1528 | "unicode-ident",
1529 | ]
1530 |
1531 | [[package]]
1532 | name = "termcolor"
1533 | version = "1.2.0"
1534 | source = "registry+https://github.com/rust-lang/crates.io-index"
1535 | checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
1536 | dependencies = [
1537 | "winapi-util",
1538 | ]
1539 |
1540 | [[package]]
1541 | name = "thiserror"
1542 | version = "1.0.39"
1543 | source = "registry+https://github.com/rust-lang/crates.io-index"
1544 | checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c"
1545 | dependencies = [
1546 | "thiserror-impl",
1547 | ]
1548 |
1549 | [[package]]
1550 | name = "thiserror-impl"
1551 | version = "1.0.39"
1552 | source = "registry+https://github.com/rust-lang/crates.io-index"
1553 | checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e"
1554 | dependencies = [
1555 | "proc-macro2",
1556 | "quote",
1557 | "syn",
1558 | ]
1559 |
1560 | [[package]]
1561 | name = "time"
1562 | version = "0.3.20"
1563 | source = "registry+https://github.com/rust-lang/crates.io-index"
1564 | checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
1565 | dependencies = [
1566 | "itoa",
1567 | "serde",
1568 | "time-core",
1569 | "time-macros",
1570 | ]
1571 |
1572 | [[package]]
1573 | name = "time-core"
1574 | version = "0.1.0"
1575 | source = "registry+https://github.com/rust-lang/crates.io-index"
1576 | checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
1577 |
1578 | [[package]]
1579 | name = "time-macros"
1580 | version = "0.2.8"
1581 | source = "registry+https://github.com/rust-lang/crates.io-index"
1582 | checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36"
1583 | dependencies = [
1584 | "time-core",
1585 | ]
1586 |
1587 | [[package]]
1588 | name = "tinyvec"
1589 | version = "1.6.0"
1590 | source = "registry+https://github.com/rust-lang/crates.io-index"
1591 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
1592 | dependencies = [
1593 | "tinyvec_macros",
1594 | ]
1595 |
1596 | [[package]]
1597 | name = "tinyvec_macros"
1598 | version = "0.1.1"
1599 | source = "registry+https://github.com/rust-lang/crates.io-index"
1600 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
1601 |
1602 | [[package]]
1603 | name = "tokio"
1604 | version = "1.26.0"
1605 | source = "registry+https://github.com/rust-lang/crates.io-index"
1606 | checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64"
1607 | dependencies = [
1608 | "autocfg",
1609 | "bytes",
1610 | "libc",
1611 | "memchr",
1612 | "mio",
1613 | "parking_lot",
1614 | "pin-project-lite",
1615 | "signal-hook-registry",
1616 | "socket2",
1617 | "tokio-macros",
1618 | "windows-sys",
1619 | ]
1620 |
1621 | [[package]]
1622 | name = "tokio-macros"
1623 | version = "1.8.2"
1624 | source = "registry+https://github.com/rust-lang/crates.io-index"
1625 | checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
1626 | dependencies = [
1627 | "proc-macro2",
1628 | "quote",
1629 | "syn",
1630 | ]
1631 |
1632 | [[package]]
1633 | name = "tokio-rustls"
1634 | version = "0.23.4"
1635 | source = "registry+https://github.com/rust-lang/crates.io-index"
1636 | checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
1637 | dependencies = [
1638 | "rustls",
1639 | "tokio",
1640 | "webpki",
1641 | ]
1642 |
1643 | [[package]]
1644 | name = "tokio-util"
1645 | version = "0.7.7"
1646 | source = "registry+https://github.com/rust-lang/crates.io-index"
1647 | checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2"
1648 | dependencies = [
1649 | "bytes",
1650 | "futures-core",
1651 | "futures-sink",
1652 | "pin-project-lite",
1653 | "tokio",
1654 | "tracing",
1655 | ]
1656 |
1657 | [[package]]
1658 | name = "tolerable"
1659 | version = "0.2.1"
1660 | dependencies = [
1661 | "actix-web",
1662 | "actix-web-prom",
1663 | "anyhow",
1664 | "array_tool",
1665 | "awc",
1666 | "base64 0.21.0",
1667 | "cached",
1668 | "config",
1669 | "ctor",
1670 | "docker-image-reference",
1671 | "lazy_static",
1672 | "log",
1673 | "pretty_env_logger",
1674 | "prometheus",
1675 | "regex",
1676 | "rustls",
1677 | "rustls-pemfile",
1678 | "serde",
1679 | "serde_json",
1680 | "strum",
1681 | "strum_macros",
1682 | "thiserror",
1683 | ]
1684 |
1685 | [[package]]
1686 | name = "toml"
1687 | version = "0.5.11"
1688 | source = "registry+https://github.com/rust-lang/crates.io-index"
1689 | checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
1690 | dependencies = [
1691 | "serde",
1692 | ]
1693 |
1694 | [[package]]
1695 | name = "tracing"
1696 | version = "0.1.37"
1697 | source = "registry+https://github.com/rust-lang/crates.io-index"
1698 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
1699 | dependencies = [
1700 | "cfg-if",
1701 | "log",
1702 | "pin-project-lite",
1703 | "tracing-core",
1704 | ]
1705 |
1706 | [[package]]
1707 | name = "tracing-core"
1708 | version = "0.1.30"
1709 | source = "registry+https://github.com/rust-lang/crates.io-index"
1710 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
1711 | dependencies = [
1712 | "once_cell",
1713 | ]
1714 |
1715 | [[package]]
1716 | name = "typenum"
1717 | version = "1.16.0"
1718 | source = "registry+https://github.com/rust-lang/crates.io-index"
1719 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
1720 |
1721 | [[package]]
1722 | name = "ucd-trie"
1723 | version = "0.1.5"
1724 | source = "registry+https://github.com/rust-lang/crates.io-index"
1725 | checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
1726 |
1727 | [[package]]
1728 | name = "unicode-bidi"
1729 | version = "0.3.11"
1730 | source = "registry+https://github.com/rust-lang/crates.io-index"
1731 | checksum = "524b68aca1d05e03fdf03fcdce2c6c94b6daf6d16861ddaa7e4f2b6638a9052c"
1732 |
1733 | [[package]]
1734 | name = "unicode-ident"
1735 | version = "1.0.8"
1736 | source = "registry+https://github.com/rust-lang/crates.io-index"
1737 | checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
1738 |
1739 | [[package]]
1740 | name = "unicode-normalization"
1741 | version = "0.1.22"
1742 | source = "registry+https://github.com/rust-lang/crates.io-index"
1743 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
1744 | dependencies = [
1745 | "tinyvec",
1746 | ]
1747 |
1748 | [[package]]
1749 | name = "unicode-xid"
1750 | version = "0.2.4"
1751 | source = "registry+https://github.com/rust-lang/crates.io-index"
1752 | checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
1753 |
1754 | [[package]]
1755 | name = "untrusted"
1756 | version = "0.7.1"
1757 | source = "registry+https://github.com/rust-lang/crates.io-index"
1758 | checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
1759 |
1760 | [[package]]
1761 | name = "url"
1762 | version = "2.3.1"
1763 | source = "registry+https://github.com/rust-lang/crates.io-index"
1764 | checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
1765 | dependencies = [
1766 | "form_urlencoded",
1767 | "idna",
1768 | "percent-encoding",
1769 | ]
1770 |
1771 | [[package]]
1772 | name = "version_check"
1773 | version = "0.9.4"
1774 | source = "registry+https://github.com/rust-lang/crates.io-index"
1775 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
1776 |
1777 | [[package]]
1778 | name = "wasi"
1779 | version = "0.11.0+wasi-snapshot-preview1"
1780 | source = "registry+https://github.com/rust-lang/crates.io-index"
1781 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
1782 |
1783 | [[package]]
1784 | name = "wasm-bindgen"
1785 | version = "0.2.84"
1786 | source = "registry+https://github.com/rust-lang/crates.io-index"
1787 | checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
1788 | dependencies = [
1789 | "cfg-if",
1790 | "wasm-bindgen-macro",
1791 | ]
1792 |
1793 | [[package]]
1794 | name = "wasm-bindgen-backend"
1795 | version = "0.2.84"
1796 | source = "registry+https://github.com/rust-lang/crates.io-index"
1797 | checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
1798 | dependencies = [
1799 | "bumpalo",
1800 | "log",
1801 | "once_cell",
1802 | "proc-macro2",
1803 | "quote",
1804 | "syn",
1805 | "wasm-bindgen-shared",
1806 | ]
1807 |
1808 | [[package]]
1809 | name = "wasm-bindgen-macro"
1810 | version = "0.2.84"
1811 | source = "registry+https://github.com/rust-lang/crates.io-index"
1812 | checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
1813 | dependencies = [
1814 | "quote",
1815 | "wasm-bindgen-macro-support",
1816 | ]
1817 |
1818 | [[package]]
1819 | name = "wasm-bindgen-macro-support"
1820 | version = "0.2.84"
1821 | source = "registry+https://github.com/rust-lang/crates.io-index"
1822 | checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
1823 | dependencies = [
1824 | "proc-macro2",
1825 | "quote",
1826 | "syn",
1827 | "wasm-bindgen-backend",
1828 | "wasm-bindgen-shared",
1829 | ]
1830 |
1831 | [[package]]
1832 | name = "wasm-bindgen-shared"
1833 | version = "0.2.84"
1834 | source = "registry+https://github.com/rust-lang/crates.io-index"
1835 | checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
1836 |
1837 | [[package]]
1838 | name = "web-sys"
1839 | version = "0.3.61"
1840 | source = "registry+https://github.com/rust-lang/crates.io-index"
1841 | checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
1842 | dependencies = [
1843 | "js-sys",
1844 | "wasm-bindgen",
1845 | ]
1846 |
1847 | [[package]]
1848 | name = "webpki"
1849 | version = "0.22.0"
1850 | source = "registry+https://github.com/rust-lang/crates.io-index"
1851 | checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
1852 | dependencies = [
1853 | "ring",
1854 | "untrusted",
1855 | ]
1856 |
1857 | [[package]]
1858 | name = "webpki-roots"
1859 | version = "0.22.6"
1860 | source = "registry+https://github.com/rust-lang/crates.io-index"
1861 | checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
1862 | dependencies = [
1863 | "webpki",
1864 | ]
1865 |
1866 | [[package]]
1867 | name = "winapi"
1868 | version = "0.3.9"
1869 | source = "registry+https://github.com/rust-lang/crates.io-index"
1870 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
1871 | dependencies = [
1872 | "winapi-i686-pc-windows-gnu",
1873 | "winapi-x86_64-pc-windows-gnu",
1874 | ]
1875 |
1876 | [[package]]
1877 | name = "winapi-i686-pc-windows-gnu"
1878 | version = "0.4.0"
1879 | source = "registry+https://github.com/rust-lang/crates.io-index"
1880 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
1881 |
1882 | [[package]]
1883 | name = "winapi-util"
1884 | version = "0.1.5"
1885 | source = "registry+https://github.com/rust-lang/crates.io-index"
1886 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
1887 | dependencies = [
1888 | "winapi",
1889 | ]
1890 |
1891 | [[package]]
1892 | name = "winapi-x86_64-pc-windows-gnu"
1893 | version = "0.4.0"
1894 | source = "registry+https://github.com/rust-lang/crates.io-index"
1895 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1896 |
1897 | [[package]]
1898 | name = "windows-sys"
1899 | version = "0.45.0"
1900 | source = "registry+https://github.com/rust-lang/crates.io-index"
1901 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
1902 | dependencies = [
1903 | "windows-targets",
1904 | ]
1905 |
1906 | [[package]]
1907 | name = "windows-targets"
1908 | version = "0.42.1"
1909 | source = "registry+https://github.com/rust-lang/crates.io-index"
1910 | checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
1911 | dependencies = [
1912 | "windows_aarch64_gnullvm",
1913 | "windows_aarch64_msvc",
1914 | "windows_i686_gnu",
1915 | "windows_i686_msvc",
1916 | "windows_x86_64_gnu",
1917 | "windows_x86_64_gnullvm",
1918 | "windows_x86_64_msvc",
1919 | ]
1920 |
1921 | [[package]]
1922 | name = "windows_aarch64_gnullvm"
1923 | version = "0.42.1"
1924 | source = "registry+https://github.com/rust-lang/crates.io-index"
1925 | checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
1926 |
1927 | [[package]]
1928 | name = "windows_aarch64_msvc"
1929 | version = "0.42.1"
1930 | source = "registry+https://github.com/rust-lang/crates.io-index"
1931 | checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
1932 |
1933 | [[package]]
1934 | name = "windows_i686_gnu"
1935 | version = "0.42.1"
1936 | source = "registry+https://github.com/rust-lang/crates.io-index"
1937 | checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
1938 |
1939 | [[package]]
1940 | name = "windows_i686_msvc"
1941 | version = "0.42.1"
1942 | source = "registry+https://github.com/rust-lang/crates.io-index"
1943 | checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
1944 |
1945 | [[package]]
1946 | name = "windows_x86_64_gnu"
1947 | version = "0.42.1"
1948 | source = "registry+https://github.com/rust-lang/crates.io-index"
1949 | checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
1950 |
1951 | [[package]]
1952 | name = "windows_x86_64_gnullvm"
1953 | version = "0.42.1"
1954 | source = "registry+https://github.com/rust-lang/crates.io-index"
1955 | checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
1956 |
1957 | [[package]]
1958 | name = "windows_x86_64_msvc"
1959 | version = "0.42.1"
1960 | source = "registry+https://github.com/rust-lang/crates.io-index"
1961 | checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
1962 |
1963 | [[package]]
1964 | name = "yaml-rust"
1965 | version = "0.4.5"
1966 | source = "registry+https://github.com/rust-lang/crates.io-index"
1967 | checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
1968 | dependencies = [
1969 | "linked-hash-map",
1970 | ]
1971 |
1972 | [[package]]
1973 | name = "zstd"
1974 | version = "0.12.3+zstd.1.5.2"
1975 | source = "registry+https://github.com/rust-lang/crates.io-index"
1976 | checksum = "76eea132fb024e0e13fd9c2f5d5d595d8a967aa72382ac2f9d39fcc95afd0806"
1977 | dependencies = [
1978 | "zstd-safe",
1979 | ]
1980 |
1981 | [[package]]
1982 | name = "zstd-safe"
1983 | version = "6.0.4+zstd.1.5.4"
1984 | source = "registry+https://github.com/rust-lang/crates.io-index"
1985 | checksum = "7afb4b54b8910cf5447638cb54bf4e8a65cbedd783af98b98c62ffe91f185543"
1986 | dependencies = [
1987 | "libc",
1988 | "zstd-sys",
1989 | ]
1990 |
1991 | [[package]]
1992 | name = "zstd-sys"
1993 | version = "2.0.7+zstd.1.5.4"
1994 | source = "registry+https://github.com/rust-lang/crates.io-index"
1995 | checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5"
1996 | dependencies = [
1997 | "cc",
1998 | "libc",
1999 | "pkg-config",
2000 | ]
2001 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tolerable"
3 | version = "0.2.1"
4 | edition = "2021"
5 | repository = "https://github.com/PeterGrace/tolerable"
6 | description = "kubernetes webhook to set configurable cpu architecture tolerations"
7 | license = "MIT"
8 |
9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
10 | [dev-dependencies]
11 | ctor = "0.1.26"
12 | [dependencies]
13 | anyhow = "1.0.69"
14 | pretty_env_logger = "0.4.0"
15 | log = "0.4.17"
16 | serde = {version = "1.0.154", features=["derive"]}
17 | serde_json = "1.0.94"
18 | prometheus = "0.13.3"
19 | lazy_static = "1.4.0"
20 | actix-web = {version="4.3.1", features=["rustls"]}
21 | actix-web-prom = "0.6.0"
22 | strum = "0.24.1"
23 | strum_macros = "0.24.3"
24 | config = {version ="0.13.3", features=["toml"]}
25 | base64 = "0.21.0"
26 | rustls = "0.20.8"
27 | rustls-pemfile = "1.0.2"
28 | awc = { version = "3.1.1", features=["rustls"]}
29 | regex = "1.7.1"
30 | docker-image-reference = { git = "https://github.com/PeterGrace/docker-image-reference.git", version = "0.1.0" }
31 | cached = {version = "0.42.0"}
32 | thiserror = "1.0.39"
33 | array_tool = "1.0.3"
34 |
35 | [profile.release]
36 | strip="debuginfo"
37 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM docker.io/ubuntu:20.04
2 | ARG TARGETARCH
3 |
4 | RUN mkdir -p /opt/tolerable
5 | WORKDIR /opt/tolerable
6 | COPY ./tools/target_arch.sh /opt/tolerable
7 | COPY docker/tolerable.toml /opt/tolerable/
8 | RUN --mount=type=bind,target=/context \
9 | cp /context/target/$(/opt/tolerable/target_arch.sh)/release/tolerable /opt/tolerable/tolerable
10 | CMD ["/opt/tolerable/tolerable"]
11 | EXPOSE 8443
12 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Peter Grace
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | 
3 | # tolerable
4 | ## Auto-configure tolerations for architecture-based taints
5 | This software program was written due to the author's frustration with running a mixed-architecture kubernetes cluster. When you are running both amd64 and arm64 processors in your cluster, there is not automatic method of detecting whether an image is built for arm64 or not. This results in Pods going into CrashLoopBackOff with a log line similar to "exec format error."
6 |
7 | `tolerable` is a Kubernetes Mutating Webhook which watches the creation of Pods in the cluster. When a request for a Pod is tendered, the Mutating Webhook receives a copy of the request. It then asks the registry that houses the image whether it has an arm64 version. If the registry responds affirmatively, it patches in a pre-configured toleration to the pod so it can schedule on the specified architecture's node(s).
8 |
9 | ## quickstart (ish)
10 | there is a kustomize/ folder that has a kustomization spec for deploying the service. It relies on cert-manager to create the certificates required to enable a MutatingWebhookConfiguration. If you don't have cert-manager, you'll need to generate these certs manually and patch the containing secret into your deployment. You'll need to also include credentials into the deployment for any registries you want to pull from that need auth (docker.io, ghcr, etc). See the creds file example below for more info.
11 |
12 |
13 | ## configs
14 |
15 | ### tolerable.toml
16 | For each of these settings in `tolerable.toml`, you can override the settings via environment variable, prefixed by TOLERABLE_. Example: `TOLERABLE_SUPPORTED_ARCHITECTURES=s390x,arm64`
17 |
18 | | value | what it is |
19 | | ----- | ---------- |
20 | | ssl_key_path | path to private key, pem format |
21 | | ssl_cert_path | path to cert, pem format |
22 | | registry_credential_path | specified path to individual credential files, toml format |
23 | | supported_architectures | array of valid architectures for the kubernetes cluster |
24 | | [tolerations] | a toml object definition that contains the toleration format for the kubernetes cluster |
25 |
26 | ### tolerations
27 | This will be specific to your deployment. In my case, I set a taint on my arm64 nodes of `kubernetes.io/arch=arm64:NoSchedule` which means only a toleration that matches that taint will be allowed to schedule. The toleration for this taint is here:
28 | ```
29 | [tolerations]
30 | effect = "NoSchedule"
31 | operator = "Equal"
32 | key = "kubernetes.io/arch"
33 | ```
34 |
35 | ### creds files (e.g., docker.io.toml)
36 | Each registry that you need to auth to should be specified in a toml file, named for the registry name of the registry with .toml suffixed, and the file should contain two keys, `user` and `secret`.
37 | Example:
38 | ```
39 | $ cat creds/docker.io.toml
40 | user="foobar"
41 | secret="bazbat"
42 | ```
43 |
44 |
45 | ## Anticipatory FAQs
46 | ### Why are the creds stored as individual files?
47 | So that one can mount the credentials individually as subpaths from secrets in kubernetes
48 | ### Can you make an image of tolerable for platform X?
49 | Yes, open an issue and I'll amend the build process to build an image for it
50 |
51 |
--------------------------------------------------------------------------------
/build.rs:
--------------------------------------------------------------------------------
1 | use std::process::Command;
2 | fn main() {
3 | // note: add error checking yourself.
4 | let output = Command::new("git")
5 | .args(&["rev-parse", "HEAD"])
6 | .output()
7 | .unwrap();
8 | let git_hash = String::from_utf8(output.stdout).unwrap();
9 | println!("cargo:rustc-env=GIT_HASH={}", git_hash);
10 | }
--------------------------------------------------------------------------------
/docker/tolerable.toml:
--------------------------------------------------------------------------------
1 | log_level = "DEBUG"
2 |
--------------------------------------------------------------------------------
/justfile:
--------------------------------------------------------------------------------
1 | commit := `git rev-parse HEAD`
2 | shortcommit := `git rev-parse HEAD`
3 | transport := "docker://"
4 | registry := "docker.io"
5 | image := "petergrace/tolerable"
6 | tag := `git describe --tags`
7 |
8 | build:
9 | cross build --release --target aarch64-unknown-linux-gnu
10 | cross build --release --target x86_64-unknown-linux-gnu
11 | make-image:
12 | docker buildx build --no-cache --push --platform linux/amd64,linux/arm64/v8 \
13 | -t {{registry}}/{{image}}:latest \
14 | -t {{registry}}/{{image}}:{{shortcommit}} \
15 | -t {{registry}}/{{image}}:{{commit}} \
16 | -t {{registry}}/{{image}}:{{tag}} \
17 | .
18 |
19 | release-patch:
20 | cargo release --no-publish --no-verify patch --execute
21 | release-minor:
22 | cargo release --no-publish --no-verify minor --execute
23 | release-major:
24 | cargo release --no-publish --no-verify minor --execute
25 |
--------------------------------------------------------------------------------
/kustomize/certificate.webhook.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: cert-manager.io/v1
3 | kind: Certificate
4 | metadata:
5 | annotations:
6 | cert-manager.io/allow-direct-injection: "true"
7 | name: tolerable-webhook
8 | spec:
9 | secretName: tolerable-tls
10 | dnsNames:
11 | - tolerable-webhook.tolerable
12 | - tolerable-webhook.tolerable.svc
13 | - tolerable-webhook.tolerable.svc.cluster.local
14 | issuerRef:
15 | name: selfsigned
16 |
--------------------------------------------------------------------------------
/kustomize/deployment.tolerable.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: tolerable-webhook
5 | spec:
6 | progressDeadlineSeconds: 600
7 | replicas: 1
8 | revisionHistoryLimit: 10
9 | selector:
10 | matchLabels:
11 | app.kubernetes.io/name: tolerable
12 | strategy:
13 | rollingUpdate:
14 | maxSurge: 25%
15 | maxUnavailable: 25%
16 | type: RollingUpdate
17 | template:
18 | metadata:
19 | creationTimestamp: null
20 | labels:
21 | app.kubernetes.io/name: tolerable
22 | spec:
23 | automountServiceAccountToken: false
24 | containers:
25 | - image: SET-IN-KUSTOMIZE/tolerable
26 | imagePullPolicy: Always
27 | livenessProbe:
28 | failureThreshold: 3
29 | httpGet:
30 | path: /health
31 | port: 8443
32 | scheme: HTTPS
33 | initialDelaySeconds: 300
34 | periodSeconds: 10
35 | successThreshold: 1
36 | timeoutSeconds: 1
37 | name: tolerable
38 | ports:
39 | - containerPort: 8443
40 | protocol: TCP
41 | readinessProbe:
42 | failureThreshold: 3
43 | httpGet:
44 | path: /health
45 | port: 8443
46 | scheme: HTTPS
47 | initialDelaySeconds: 1
48 | periodSeconds: 10
49 | successThreshold: 1
50 | timeoutSeconds: 1
51 | resources: {}
52 | terminationMessagePath: /dev/termination-log
53 | terminationMessagePolicy: File
54 | volumeMounts:
55 | - mountPath: /opt/tolerable/ssl
56 | name: tls-certs
57 | - mountPath: /opt/tolerable/tolerable.toml
58 | name: config
59 | subPath: tolerable.toml
60 | dnsPolicy: ClusterFirst
61 | restartPolicy: Always
62 | schedulerName: default-scheduler
63 | securityContext:
64 | fsGroup: 10000
65 | runAsUser: 10000
66 | terminationGracePeriodSeconds: 30
67 | volumes:
68 | - configMap:
69 | name: tolerable-config
70 | name: config
71 | - secret:
72 | secretName: tolerable-tls
73 | name: tls-certs
74 |
--------------------------------------------------------------------------------
/kustomize/deployment.ubuntu-test.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: ubuntu-test
5 | spec:
6 | replicas: 1
7 | selector:
8 | matchLabels:
9 | app.kubernetes.io/name: ubuntu-test
10 | template:
11 | metadata:
12 | labels:
13 | app.kubernetes.io/name: ubuntu-test
14 | spec:
15 | containers:
16 | - image: docker.io/ubuntu
17 | imagePullPolicy: Always
18 | name: ubuntu-test
19 | command:
20 | - /bin/sleep
21 | - infinity
22 |
--------------------------------------------------------------------------------
/kustomize/issuer.selfsigned.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: cert-manager.io/v1
3 | kind: Issuer
4 | metadata:
5 | name: selfsigned
6 | spec:
7 | selfSigned: {}
8 |
--------------------------------------------------------------------------------
/kustomize/kustomization.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: kustomize.config.k8s.io/v1beta1
2 | kind: Kustomization
3 | namespace: tolerable
4 |
5 | commonLabels:
6 | app.kubernetes.io/name: tolerable
7 |
8 | configMapGenerator:
9 | - files:
10 | - tolerable.toml
11 | name: tolerable-config
12 |
13 | images:
14 | - name: SET-IN-KUSTOMIZE/tolerable
15 | newName: docker.io/petergrace/tolerable
16 | newTag: latest
17 |
18 |
19 | resources:
20 | - ns.tolerable.yaml
21 | - certificate.webhook.yaml
22 | - issuer.selfsigned.yaml
23 | - service.tolerable.yaml
24 | - svcacct.tolerable.yaml
25 | - deployment.tolerable.yaml
26 | - mutatingwebhook.yaml
27 |
--------------------------------------------------------------------------------
/kustomize/mutatingwebhook.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: admissionregistration.k8s.io/v1
3 | kind: MutatingWebhookConfiguration
4 | metadata:
5 | name: tolerable-configuration
6 | annotations:
7 | cert-manager.io/inject-ca-from: tolerable/tolerable-webhook
8 | webhooks:
9 | - clientConfig:
10 | caBundle: Cg==
11 | service:
12 | name: tolerable-webhook
13 | path: /mutate
14 | port: 8443
15 | namespace: "tolerable"
16 | sideEffects: None
17 | admissionReviewVersions: ["v1beta1"]
18 | failurePolicy: Ignore
19 | name: webhook.tolerable.dev
20 | rules:
21 | - apiGroups:
22 | - ""
23 | apiVersions:
24 | - "v1"
25 | operations:
26 | - CREATE
27 | - UPDATE
28 | resources:
29 | - pods
30 | scope: "Namespaced"
31 |
--------------------------------------------------------------------------------
/kustomize/ns.tolerable.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: tolerable
5 |
--------------------------------------------------------------------------------
/kustomize/service.tolerable.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: tolerable-webhook
5 | spec:
6 | internalTrafficPolicy: Cluster
7 | type: ClusterIP
8 | ports:
9 | - name: https
10 | port: 8443
11 | protocol: TCP
12 | targetPort: 8443
13 |
--------------------------------------------------------------------------------
/kustomize/svcacct.tolerable.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: ServiceAccount
3 | metadata:
4 | name: tolerable
5 |
--------------------------------------------------------------------------------
/kustomize/tolerable.toml:
--------------------------------------------------------------------------------
1 | log_level = "INFO"
2 | ssl_key_path = "/opt/tolerable/ssl/tls.key"
3 | ssl_cert_path = "/opt/tolerable/ssl/tls.crt"
4 | registry_credential_path = "/opt/tolerable/creds"
5 | supported_architectures = [ "amd64", "arm64" ]
6 | [tolerations]
7 | effect = "NoSchedule"
8 | operator = "Equal"
9 | key = "kubernetes.io/arch"
10 | value= "arm64"
11 |
--------------------------------------------------------------------------------
/src/consts.rs:
--------------------------------------------------------------------------------
1 | pub const APP_NAME: &str = "tolerable";
2 | pub const DOCKER_IMAGE_REGEXP: &str = r#"^(?P[\w.\-_]+((?::\d+|)(?=/[a-z0-9._-]+/[a-z0-9._-]+))|)\(?:/|)(?P[a-z0-9.\-_]+(?:/[a-z0-9.\-_]+|))(:(?P[\w.\-_]{1,127})|)$"#;
3 | pub const TOKEN_AUTH_REGEXP: &str = r#"^Bearer realm="(?P.+)",service="(?P.+)",scope="(?P.+)"$"#;
4 |
5 | // amusingly enough, it seems that docker.io is the only registry allowed to have a different actual dns name,
6 | // and everyone just seems to go along with this.
7 | pub const ACTUAL_DOCKER_REGISTRY: &str = r#"registry-1.docker.io"#;
8 |
--------------------------------------------------------------------------------
/src/main.rs:
--------------------------------------------------------------------------------
1 | mod consts;
2 | mod metrics;
3 | mod models;
4 | mod mutation;
5 | mod tests;
6 | mod manifest;
7 |
8 | #[macro_use]
9 | extern crate log;
10 |
11 | #[macro_use]
12 | extern crate lazy_static;
13 | #[macro_use]
14 | extern crate prometheus;
15 |
16 | use actix_web::{middleware, web, App, HttpResponse, HttpServer};
17 |
18 | use crate::metrics::{register_metrics, APPVER, STATIC_PROM};
19 | use crate::mutation::mutate_handler;
20 | use config::{Config};
21 | use rustls::ServerConfig;
22 | use rustls_pemfile;
23 | use std::env;
24 | use std::env::set_var;
25 | use std::fs;
26 | use std::io::BufReader;
27 | use std::sync::RwLock;
28 |
29 | lazy_static! {
30 | static ref SETTINGS: RwLock = RwLock::new({
31 | let cfg_file = match std::env::var("CONFIG_FILE_PATH") {
32 | Ok(s) => s,
33 | Err(_e) => { "./tolerable.toml".to_string()}
34 | };
35 | let settings = match Config::builder()
36 | .add_source(config::File::with_name(&cfg_file))
37 | .add_source(
38 | config::Environment::with_prefix("TOLERABLE")
39 | .try_parsing(true)
40 | .list_separator(",")
41 | .with_list_parse_key("supported_architectures")
42 | )
43 | .build()
44 | {
45 | Ok(s) => s,
46 | Err(e) => {
47 | panic!("{}", e);
48 | }
49 | };
50 | settings
51 | });
52 | }
53 |
54 | #[actix_web::main]
55 | async fn main() -> anyhow::Result<()> {
56 | // initialize logging
57 | match read_setting_string("log_level") {
58 | Ok(log_level) => set_var("RUST_LOG", log_level),
59 | Err(_e) => {}
60 | }
61 |
62 | pretty_env_logger::init();
63 |
64 | // get prometheus metrics ready to rock
65 | register_metrics();
66 |
67 | // measure our first metric, the appver
68 | let appdata = APPVER.with_label_values(&[env!("CARGO_PKG_VERSION"), env!("GIT_HASH")]);
69 | appdata.set(1 as f64);
70 | debug!("tolerable cargo:{}, githash:{}", env!("CARGO_PKG_VERSION"),env!("GIT_HASH"));
71 |
72 | let ssl_key_path = match read_setting_string("ssl_key_path") {
73 | Ok(s) => s,
74 | Err(e) => {panic!("{}",e);}
75 | };
76 | let ssl_cert_path = match read_setting_string("ssl_cert_path") {
77 | Ok(s) => s,
78 | Err(e) => {panic!("{}",e);}
79 | };
80 | let versions = rustls::ALL_VERSIONS.to_vec();
81 | let suites = rustls::ALL_CIPHER_SUITES.to_vec();
82 | let certs = load_certs(&ssl_cert_path);
83 | let privkey = load_private_key(&ssl_key_path);
84 | let rustls_config = ServerConfig::builder()
85 | .with_cipher_suites(&suites)
86 | .with_safe_default_kx_groups()
87 | .with_protocol_versions(&versions)
88 | .unwrap()
89 | .with_no_client_auth()
90 | .with_single_cert(certs, privkey)
91 | .unwrap();
92 | // fire up server and lets go!
93 | HttpServer::new(move || {
94 | App::new()
95 | .wrap(middleware::Logger::default())
96 | .wrap(STATIC_PROM.clone())
97 | .service(mutate_handler)
98 | .route("/health", web::get().to(HttpResponse::Ok))
99 | })
100 | .bind_rustls(("0.0.0.0", 8443), rustls_config)?
101 | .run()
102 | .await?;
103 | Ok(())
104 | }
105 |
106 | fn load_private_key(filename: &str) -> rustls::PrivateKey {
107 | let keyfile = fs::File::open(filename).expect("cannot open private key file");
108 | let mut reader = BufReader::new(keyfile);
109 |
110 | loop {
111 | match rustls_pemfile::read_one(&mut reader).expect("cannot parse private key .pem file") {
112 | Some(rustls_pemfile::Item::RSAKey(key)) => return rustls::PrivateKey(key),
113 | Some(rustls_pemfile::Item::PKCS8Key(key)) => return rustls::PrivateKey(key),
114 | Some(rustls_pemfile::Item::ECKey(key)) => return rustls::PrivateKey(key),
115 | None => break,
116 | _ => {}
117 | }
118 | }
119 |
120 | panic!(
121 | "no keys found in {:?} (encrypted keys not supported)",
122 | filename
123 | );
124 | }
125 | fn load_certs(filename: &str) -> Vec {
126 | let certfile = fs::File::open(filename).expect("cannot open certificate file");
127 | let mut reader = BufReader::new(certfile);
128 | rustls_pemfile::certs(&mut reader)
129 | .unwrap()
130 | .iter()
131 | .map(|v| rustls::Certificate(v.clone()))
132 | .collect()
133 | }
134 |
135 | fn read_setting_string(key: &str) -> anyhow::Result {
136 | match SETTINGS.read().unwrap().get::(&key) {
137 | Ok(s) => Ok(s),
138 | Err(_e) => {
139 | Err(anyhow::anyhow!("unable to read config setting {}",key))
140 | }
141 | }
142 | }
--------------------------------------------------------------------------------
/src/manifest.rs:
--------------------------------------------------------------------------------
1 | use std::fmt;
2 | use std::path::Path;
3 | use anyhow::{bail};
4 | use awc::{Client, ClientRequest, SendClientRequest};
5 | use awc::error::JsonPayloadError;
6 | use config::Config;
7 | use regex::Regex;
8 | use docker_image_reference::Reference;
9 | use crate::read_setting_string;
10 | use cached::proc_macro::cached;
11 | use serde_json::Value;
12 | use crate::consts::*;
13 |
14 |
15 | lazy_static! {
16 | static ref DOCKER_RE: Regex = Regex::new(DOCKER_IMAGE_REGEXP).unwrap();
17 | static ref TOKEN_AUTH_RE: Regex = Regex::new(TOKEN_AUTH_REGEXP).unwrap();
18 | }
19 |
20 | #[cached]
21 | pub async fn validate_manifest(image: String) -> Option> {
22 |
23 | let mut manifest_ref: Reference = match Reference::from_str(&image){
24 | Ok(m) => m,
25 | Err(e) => {
26 | warn!{"unable to match manifest from image string: {}", e};
27 | return None;
28 | }
29 | };
30 | // first attempt to hit the endpoint
31 | let mut registryport = "".to_string();
32 | // we will start with the docker hub registry as its the assumed default.
33 | let mut registry = "docker.io";
34 | let mut tag = "";
35 | if manifest_ref.registry_name().is_some() {
36 | registry = manifest_ref.registry_name().unwrap();
37 | }
38 | let cred = get_credentials_for_registry(registry.to_string()).await;
39 | if registry == "docker.io" {
40 | // see consts.rs for commentary
41 | registry = ACTUAL_DOCKER_REGISTRY;
42 | }
43 | if manifest_ref.registry_port().is_some() {
44 | registryport = format!("{}{}", registry, manifest_ref.registry_port().unwrap())
45 | } else {
46 | registryport = format!("{}", registry);
47 | }
48 | if manifest_ref.tag().is_some() {
49 | tag = manifest_ref.tag().unwrap();
50 | } else {
51 | tag = "latest";
52 | }
53 |
54 | // Docker legacy image names can be specified without a repository name ('nginx' vs 'library/nginx') so
55 | // we will fix these here, as the backend for docker.io at least requires that in the api call.
56 | let mut image_name: String;
57 | if !manifest_ref.name().contains('/') {
58 | image_name = format!("library/{}", manifest_ref.name());
59 | } else {
60 | image_name = manifest_ref.name().to_owned();
61 | }
62 |
63 | let url = format!("https://{registryport}/v2/{}/manifests/{tag}", image_name);
64 | let token = get_jwt(url.clone(), cred).await;
65 | let client = Client::new();
66 | let image_manifest_types = vec![
67 | "application/vnd.oci.image.index.v1+json",
68 | "application/vnd.docker.distribution.manifest.list.v2+json"
69 | ];
70 | let mut manifest_req :ClientRequest= client.get(&url).insert_header(("Accept", image_manifest_types.join(",")));
71 | if token.is_some() {
72 | manifest_req = manifest_req.bearer_auth(token.unwrap());
73 | }
74 | debug!("MANIFEST REQ: {:#?}", manifest_req);
75 | let mut manifest_rs = match manifest_req.send().await {
76 | Ok(r) => r,
77 | Err(e) => {
78 | warn!("Unable to contact for manifest request: {e}");
79 | return None;
80 | }
81 | };
82 |
83 |
84 | // due to the fact that docker.io returns a mime type that actix-web doesn't like, we'll save the body to
85 | // a variable and attempt to convert it to json there.
86 | let rs_body = match manifest_rs.body().await {
87 | Ok(b) => b,
88 | Err(e) => {
89 | warn!("Unable to decode payload of manifest response: {e}");
90 | return None;
91 | }
92 | };
93 |
94 | let rs_json: Value = match serde_json::from_slice(rs_body.as_ref()) {
95 | Ok(m) => m,
96 | Err(e) => {
97 | warn!("Error decoding result from manifest request: {e}");
98 | debug!("{:#?}", manifest_rs);
99 | debug!("{:#?}", manifest_rs.body().await);
100 | return None;
101 | }
102 | };
103 |
104 | // depending on schemaVersion, we need to work a little differently.
105 | let jsondata: String = format!("{:#?}",rs_json);
106 | let schemaVersion: u64 = match rs_json.get("schemaVersion") {
107 | Some(v) => v.as_u64().unwrap(),
108 | None => {
109 | warn!("Response had no schemaVersion, so we can't deduce where a platform value would live.");
110 | return None;
111 | }
112 | };
113 | return match schemaVersion {
114 | 1 => get_version_1_arches(&rs_json),
115 | 2 => get_version_2_arches(&rs_json),
116 | _ => {
117 | warn!("We received a value we did not expect for schemaVersion: {}", schemaVersion);
118 | None
119 | }
120 | }
121 | }
122 |
123 | pub fn get_version_1_arches(json: &Value) -> Option> {
124 | let mut arches:Vec = vec![];
125 | match json.get("architecture") {
126 | Some(s) => arches.push(s.as_str().unwrap().to_string()),
127 | None => {
128 | warn!("Schema version 1, but no architecture specified");
129 | return None
130 | }
131 | };
132 | Some(arches)
133 | }
134 |
135 | pub fn get_version_2_arches(json: &Value) -> Option> {
136 | let manifests = match json.get("manifests") {
137 | Some(m) => m.as_array().unwrap(),
138 | None => {
139 | warn!("no manifests found: {:#?}", json);
140 | return None;
141 | }
142 | };
143 | let mut arches = Vec::new();
144 | for mani in manifests {
145 | let platform = match mani.get("platform") {
146 | Some(p) => p,
147 | None => {
148 | warn!("no platforms detected: {:#?}", mani);
149 | return None;
150 | }
151 | };
152 | let arch = match platform.get("architecture") {
153 | Some(a) => a.as_str().unwrap(),
154 | None => {
155 | warn!("platform exists but no architecture found: {:#?}", platform);
156 | return None;
157 | }
158 | };
159 | if !arches.contains(&arch.to_string()) {
160 | arches.push(arch.to_string());
161 | }
162 | }
163 | debug!("v2 architectures discovered {:#?}", arches);
164 | Some(arches)
165 | }
166 |
167 |
168 | pub async fn get_jwt(url: String, credentials: Option) -> Option {
169 | let client = Client::new();
170 |
171 | let mut rs = match client.get(&url).send().await {
172 | Ok(r) => r,
173 | Err(e) => {
174 | warn!("Error on initial request for token data");
175 | return None;
176 | }
177 | };
178 |
179 | let auth = match rs.headers().get("www-authenticate") {
180 | Some(val) => val.to_str().unwrap(),
181 | None => {
182 | info!("we tried to query for a jwt but did not get www-authenticate header.");
183 | return None;
184 | }
185 | };
186 | let cap = TOKEN_AUTH_RE.captures(auth).unwrap();
187 | let authurl = format!("{}?service={}&scope={}",
188 | cap.name("url").unwrap().as_str(),
189 | cap.name("service").unwrap().as_str(),
190 | cap.name("scope").unwrap().as_str());
191 | let mut auth_req = client.get(authurl.clone());
192 | if credentials.is_some() {
193 | auth_req = auth_req.basic_auth(credentials.clone().unwrap().user, credentials.clone().unwrap().secret);
194 | }
195 | debug!("AUTH REQ: {:#?}", auth_req);
196 | let mut auth_rs = match auth_req
197 | .send()
198 | .await {
199 | Ok(a) => a,
200 | Err(e) => {
201 | warn!("Couldn't get token from {}: {}", authurl, e);
202 | return None;
203 | }
204 | };
205 |
206 | let body = match auth_rs.json::().await {
207 | Ok(a) => a,
208 | Err(e) => {
209 | warn!("Didn't deserialize body to json in response: {}", e);
210 | return None
211 | }
212 | };
213 | match body.get("token") {
214 | Some(a) => Some(a.as_str().unwrap().parse().unwrap()),
215 | None => {
216 | warn!("Couldn't find token in response.");
217 | None
218 | }
219 | }
220 | }
221 |
222 | pub async fn get_credentials_for_registry(registry: String) -> Option {
223 | let cred_path = match read_setting_string("registry_credential_path") {
224 | Ok(path) => path,
225 | Err(e) => {
226 | warn!{"cred path not found in config (registry_credential_path)"}
227 | return None;
228 | }
229 | };
230 | let cred_file = format!("{}/{}.toml",cred_path,registry);
231 | if !Path::new(&cred_file).exists() {
232 | warn!("credential file does not exist: {}", cred_file);
233 | return None;
234 | };
235 | let cred: config::Config = match Config::builder()
236 | .add_source(config::File::with_name(&cred_file))
237 | .build(){
238 | Ok(config) => config,
239 | Err(e) => {
240 | warn!("path '{}' exists but config couldn't initialize", cred_file);
241 | return None;
242 | }
243 | };
244 |
245 | let user: String = match cred.get::("user") {
246 | Ok(user) => user,
247 | Err(e) => {
248 | warn!("In '{}', config key 'user' does not exist: {}", cred_file, e);
249 | return None;
250 | }
251 | };
252 | let secret: String = match cred.get::("secret") {
253 | Ok(secret) => secret,
254 | Err(e) => {
255 | warn!("In '{}', config key 'secret' does not exist: {}", cred_file, e);
256 | return None;
257 | }
258 | };
259 | Some(RegistryCredential {user, secret})
260 | }
261 |
262 | #[derive(Clone, Debug)]
263 | pub struct RegistryCredential {
264 | user: String,
265 | secret: String
266 | }
267 |
--------------------------------------------------------------------------------
/src/metrics.rs:
--------------------------------------------------------------------------------
1 | use crate::consts::APP_NAME;
2 | use actix_web_prom::{PrometheusMetrics, PrometheusMetricsBuilder};
3 | use prometheus::GaugeVec;
4 | lazy_static! {
5 | // setup prometheus
6 | pub static ref STATIC_PROM: PrometheusMetrics = PrometheusMetricsBuilder::new(APP_NAME)
7 | .endpoint("/metrics")
8 | .build()
9 | .unwrap();
10 | pub static ref APPVER: GaugeVec = register_gauge_vec!(
11 | format!("{}_app_info",APP_NAME),
12 | "static app labels that potentially only change at restart",
13 | &["crate_version", "git_hash"]
14 | )
15 | .unwrap();
16 | }
17 |
18 | pub fn register_metrics() {
19 | STATIC_PROM
20 | .registry
21 | .register(Box::new(APPVER.clone()))
22 | .expect("couldn't register appver metric");
23 | }
24 |
--------------------------------------------------------------------------------
/src/models.rs:
--------------------------------------------------------------------------------
1 | use serde::{Deserialize, Serialize};
2 | use serde_json::{Map, Value};
3 | use strum_macros::EnumString;
4 |
5 | #[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Default)]
6 | pub struct AdmissionReview {
7 | /// request is the incoming AdmissionRequest object
8 | #[serde(rename = "request", skip_serializing_if = "Option::is_none")]
9 | pub request: Option,
10 | /// response is the outgoing, mutated object.
11 | #[serde(rename = "response", skip_serializing_if = "Option::is_none")]
12 | pub response: Option,
13 | }
14 | #[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Default)]
15 | pub struct AdmissionRequest {
16 | /// uid is an identifier for the individual request/response
17 | pub uid: String,
18 | /// kind is the kind of the object
19 | pub kind: GroupVersionKind,
20 | /// resource is the fully-qualified resource being requested
21 | pub resource: GroupVersionResource,
22 | #[serde(rename = "subResource", skip_serializing_if = "Option::is_none")]
23 | pub sub_resource: Option,
24 | /// request_kind is the fully-qualified type of the original API request
25 | #[serde(rename = "requestKind", skip_serializing_if = "Option::is_none")]
26 | pub request_kind: Option,
27 | /// request_sub_resource is the name of the subresource of the original API request
28 | #[serde(rename = "requestSubResource", skip_serializing_if = "Option::is_none")]
29 | pub request_sub_resource: Option,
30 | /// name is the name of the object as presented in the request.
31 | #[serde(rename = "name", skip_serializing_if = "Option::is_none")]
32 | pub name: Option,
33 | /// namespace is the namespace associated with the request, if any.
34 | #[serde(rename = "namespace", skip_serializing_if = "Option::is_none")]
35 | pub namespace: Option,
36 | /// operation is the operation being performed, which may be different than requested.
37 | /// For example, a PATCH might wind up resulting in a CREATE or UPDATE operation.
38 | pub operation: Operation,
39 | /// user_info is information about the requesting user
40 | #[serde(rename = "userInfo")]
41 | pub user_info: Map,
42 | /// object is the object from the incoming request.
43 | #[serde(rename = "object", skip_serializing_if = "Option::is_none")]
44 | pub object: Option