From f3b93f1504faad1e35b8dda0e84f88f940b83d69 Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Thu, 1 Jul 2021 18:12:56 +0200 Subject: [PATCH 01/15] Add CoAP discovery handler implementation --- Cargo.lock | 403 +++++++++++++----- Cargo.toml | 2 + .../helm/templates/custom-configuration.yaml | 16 +- .../coap-discovery-handler/.gitignore | 5 + .../coap-discovery-handler/Cargo.toml | 23 + .../Dockerfile.discovery-handler | 20 + .../src/discovery_handler.rs | 257 +++++++++++ .../src/discovery_utils.rs | 122 ++++++ .../coap-discovery-handler/src/main.rs | 31 ++ samples/brokers/coap-broker/Cargo.toml | 19 + samples/brokers/coap-broker/src/http_coap.rs | 71 +++ samples/brokers/coap-broker/src/main.rs | 296 +++++++++++++ 12 files changed, 1162 insertions(+), 103 deletions(-) create mode 100644 discovery-handler-modules/coap-discovery-handler/.gitignore create mode 100644 discovery-handler-modules/coap-discovery-handler/Cargo.toml create mode 100644 discovery-handler-modules/coap-discovery-handler/Dockerfile.discovery-handler create mode 100644 discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs create mode 100644 discovery-handler-modules/coap-discovery-handler/src/discovery_utils.rs create mode 100644 discovery-handler-modules/coap-discovery-handler/src/main.rs create mode 100644 samples/brokers/coap-broker/Cargo.toml create mode 100644 samples/brokers/coap-broker/src/http_coap.rs create mode 100644 samples/brokers/coap-broker/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 1c1041707..76668e2a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "actix" version = "0.11.1" @@ -115,8 +117,8 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655" dependencies = [ - "quote", - "syn", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -125,8 +127,8 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbcb2b608f0accc2f5bcf3dd872194ce13d94ee45b571487035864cf966b04ef" dependencies = [ - "quote", - "syn", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -307,9 +309,9 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad26f77093333e0e7c6ffe54ebe3582d908a104e448723eec6d43d08b07143fb" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -318,9 +320,9 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d44b8fee1ced9671ba043476deddef739dd0959bf77030b26b738cc591737a7" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -500,7 +502,7 @@ dependencies = [ "tokio-signal", "tonic", "tower", - "warp", + "warp 0.2.5", ] [[package]] @@ -529,9 +531,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.40" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b" +checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61" [[package]] name = "async-channel" @@ -668,9 +670,9 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -685,9 +687,9 @@ version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -976,9 +978,9 @@ checksum = "370f715b81112975b1b69db93e0b56ea4cd4e5002ac43b2da8474106a54096a1" dependencies = [ "heck", "proc-macro-error", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -990,6 +992,65 @@ dependencies = [ "bitflags", ] +[[package]] +name = "coap" +version = "0.9.2" +source = "git+https://github.com/Covertness/coap-rs#aac20c39925511cb2fa9653a32c0cb02bfd0b1f0" +dependencies = [ + "bytes 0.5.6", + "coap-lite", + "futures 0.3.15", + "log", + "num-derive", + "num-traits", + "regex", + "serde", + "tokio 0.2.25", + "tokio-util 0.2.0", + "url 1.7.2", +] + +[[package]] +name = "coap-broker" +version = "0.1.0" +dependencies = [ + "akri-shared", + "anyhow", + "coap", + "coap-lite", + "env_logger", + "futures 0.3.15", + "log", + "tokio 1.6.1", + "tokio-stream", + "warp 0.3.1", +] + +[[package]] +name = "coap-discovery-handler" +version = "0.6.8" +dependencies = [ + "akri-discovery-utils", + "anyhow", + "async-trait", + "coap", + "coap-lite", + "env_logger", + "log", + "mockall", + "serde", + "serde_derive", + "serde_json", + "tokio 0.2.25", + "tonic", +] + +[[package]] +name = "coap-lite" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15e8642b7913b70e905e3d9bc1e01ff25ddcb650344d83e90ebbba9d2a4e03b" + [[package]] name = "concurrent-queue" version = "1.2.2" @@ -1170,8 +1231,8 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" dependencies = [ - "quote", - "syn", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -1192,9 +1253,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cc7b9cef1e351660e5443924e4f43ab25fbbed3e9a5f052df3677deb4d6b320" dependencies = [ "convert_case", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -1282,16 +1343,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" dependencies = [ "heck", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] name = "env_logger" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" dependencies = [ "atty", "humantime", @@ -1478,9 +1539,9 @@ checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121" dependencies = [ "autocfg", "proc-macro-hack", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -1867,6 +1928,15 @@ dependencies = [ "bytes 0.5.6", ] +[[package]] +name = "input_buffer" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413" +dependencies = [ + "bytes 1.0.1", +] + [[package]] name = "instant" version = "0.1.9" @@ -2232,9 +2302,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dd4234635bca06fc96c7368d038061e0aae1b00a764dc817e900dc974e3deea" dependencies = [ "cfg-if 1.0.0", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -2244,9 +2314,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e25b78d34b2b713b1d000d629079755cfc166e6a65f9f4c1c012a94305467c5" dependencies = [ "cfg-if 1.0.0", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -2317,6 +2387,17 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "num-derive" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", +] + [[package]] name = "num-integer" version = "0.1.44" @@ -2627,9 +2708,9 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -2677,9 +2758,9 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3be26700300be6d9d23264c73211d8190e755b6b5ca7a1b28230025511b52a5e" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -2688,9 +2769,9 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -2772,9 +2853,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", "version_check", ] @@ -2784,8 +2865,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.27", + "quote 1.0.9", "version_check", ] @@ -2801,13 +2882,22 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + [[package]] name = "proc-macro2" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" dependencies = [ - "unicode-xid", + "unicode-xid 0.2.2", ] [[package]] @@ -2894,9 +2984,9 @@ checksum = "537aa19b95acde10a12fec4301466386f757403de4cd4e5b4fa78fb5ecb18f72" dependencies = [ "anyhow", "itertools", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -2921,13 +3011,22 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + [[package]] name = "quote" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.27", ] [[package]] @@ -3324,9 +3423,9 @@ version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -3493,11 +3592,11 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.27", + "quote 1.0.9", "serde", "serde_derive", - "syn", + "syn 1.0.72", ] [[package]] @@ -3507,13 +3606,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" dependencies = [ "base-x", - "proc-macro2", - "quote", + "proc-macro2 1.0.27", + "quote 1.0.9", "serde", "serde_derive", "serde_json", "sha1", - "syn", + "syn 1.0.72", ] [[package]] @@ -3555,15 +3654,26 @@ dependencies = [ "sxd-document", ] +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + [[package]] name = "syn" version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "proc-macro2 1.0.27", + "quote 1.0.9", + "unicode-xid 0.2.2", ] [[package]] @@ -3613,9 +3723,9 @@ version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -3670,10 +3780,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa" dependencies = [ "proc-macro-hack", - "proc-macro2", - "quote", + "proc-macro2 1.0.27", + "quote 1.0.9", "standback", - "syn", + "syn 1.0.72", ] [[package]] @@ -3735,7 +3845,7 @@ dependencies = [ "pin-project-lite 0.1.12", "signal-hook-registry", "slab", - "tokio-macros", + "tokio-macros 0.2.6", "winapi 0.3.9", ] @@ -3750,10 +3860,12 @@ dependencies = [ "libc", "memchr", "mio 0.7.11", + "num_cpus", "once_cell", "parking_lot 0.11.1", "pin-project-lite 0.2.6", "signal-hook-registry", + "tokio-macros 1.2.0", "winapi 0.3.9", ] @@ -3835,9 +3947,20 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", +] + +[[package]] +name = "tokio-macros" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c49e3df43841dafb86046472506755d8501c5615673955f6aa17181125d13c37" +dependencies = [ + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -3898,6 +4021,17 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "tokio-stream" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8864d706fdb3cc0843a49647ac892720dac98a6eeb818b77190592cf4994066" +dependencies = [ + "futures-core", + "pin-project-lite 0.2.6", + "tokio 1.6.1", +] + [[package]] name = "tokio-sync" version = "0.1.8" @@ -3971,7 +4105,20 @@ dependencies = [ "log", "pin-project 0.4.28", "tokio 0.2.25", - "tungstenite", + "tungstenite 0.11.1", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1a5f475f1b9d077ea1017ecbc60890fda8e54942d680ca0b1d2b47cfa2d861b" +dependencies = [ + "futures-util", + "log", + "pin-project 1.0.7", + "tokio 1.6.1", + "tungstenite 0.12.0", ] [[package]] @@ -4086,10 +4233,10 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0436413ba71545bcc6c2b9a0f9d78d72deb0123c6a75ccdfe7c056f9930f5e52" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.27", "prost-build", - "quote", - "syn", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -4289,9 +4436,9 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] [[package]] @@ -4375,7 +4522,7 @@ dependencies = [ "bytes 0.5.6", "http 0.2.4", "httparse", - "input_buffer", + "input_buffer 0.3.1", "log", "rand 0.7.3", "sha-1 0.9.6", @@ -4383,6 +4530,25 @@ dependencies = [ "utf-8", ] +[[package]] +name = "tungstenite" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ada8297e8d70872fa9a551d93250a9f407beb9f37ef86494eb20012a2ff7c24" +dependencies = [ + "base64 0.13.0", + "byteorder", + "bytes 1.0.1", + "http 0.2.4", + "httparse", + "input_buffer 0.4.0", + "log", + "rand 0.8.3", + "sha-1 0.9.6", + "url 2.2.2", + "utf-8", +] + [[package]] name = "twoway" version = "0.1.8" @@ -4487,6 +4653,12 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + [[package]] name = "unicode-xid" version = "0.2.2" @@ -4608,13 +4780,42 @@ dependencies = [ "serde_json", "serde_urlencoded 0.6.1", "tokio 0.2.25", - "tokio-tungstenite", + "tokio-tungstenite 0.11.0", "tower-service", "tracing", "tracing-futures", "urlencoding", ] +[[package]] +name = "warp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "332d47745e9a0c38636dbd454729b147d16bd1ed08ae67b3ab281c4506771054" +dependencies = [ + "bytes 1.0.1", + "futures 0.3.15", + "headers", + "http 0.2.4", + "hyper 0.14.8", + "log", + "mime", + "mime_guess", + "multipart", + "percent-encoding 2.1.0", + "pin-project 1.0.7", + "scoped-tls 1.0.0", + "serde", + "serde_json", + "serde_urlencoded 0.7.0", + "tokio 1.6.1", + "tokio-stream", + "tokio-tungstenite 0.13.0", + "tokio-util 0.6.7", + "tower-service", + "tracing", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -4648,9 +4849,9 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", "wasm-bindgen-shared", ] @@ -4672,7 +4873,7 @@ version = "0.2.74" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" dependencies = [ - "quote", + "quote 1.0.9", "wasm-bindgen-macro-support", ] @@ -4682,9 +4883,9 @@ version = "0.2.74" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4860,7 +5061,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9af81f1d48039716dd825cf4a7d61d39583f8b12705994abb446bae749a977bb" dependencies = [ "heck", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", ] diff --git a/Cargo.toml b/Cargo.toml index 5fb515883..69d55aff8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "shared", "agent", "controller", + "samples/brokers/coap-broker", "samples/brokers/udev-video-broker", "webhooks/validating/configuration", "discovery-utils", @@ -15,6 +16,7 @@ members = [ "discovery-handlers/onvif", "discovery-handlers/opcua", "discovery-handlers/udev", + "discovery-handler-modules/coap-discovery-handler", "discovery-handler-modules/debug-echo-discovery-handler", "discovery-handler-modules/onvif-discovery-handler", "discovery-handler-modules/opcua-discovery-handler", diff --git a/deployment/helm/templates/custom-configuration.yaml b/deployment/helm/templates/custom-configuration.yaml index 9f38a927b..7858fac00 100644 --- a/deployment/helm/templates/custom-configuration.yaml +++ b/deployment/helm/templates/custom-configuration.yaml @@ -6,7 +6,19 @@ metadata: spec: discoveryHandler: name: {{ required "A custom.configuration.discoveryHandlerName is required." .Values.custom.configuration.discoveryHandlerName }} - discoveryDetails: {{ .Values.custom.configuration.discoveryDetails }} + discoveryDetails: |+ + multicast: {{ .Values.custom.configuration.discoveryDetails.multicast }} + multicastIpAddress: {{ .Values.custom.configuration.discoveryDetails.multicastIpAddress }} + staticIpAddresses: + {{ - toYaml .Values.custom.configuration.discoveryDetails.staticIpAddresses | nindent 6 }} + {{- if .Values.custom.configuration.discoveryDetails.queryFilter }} + queryFilter: + name: {{ .Values.custom.configuration.discoveryDetails.queryFilter.name }} + value: {{ .Values.custom.configuration.discoveryDetails.queryFilter.value }} + {{- else }} + queryFilter: null + {{- end }} + discoveryTimeoutSeconds: {{ .Values.custom.configuration.discoveryDetails.discoveryTimeoutSeconds }} {{- if .Values.custom.configuration.brokerPod.image.repository }} brokerPodSpec: containers: @@ -58,4 +70,4 @@ spec: brokerProperties: {} {{- end }} capacity: {{ .Values.custom.configuration.capacity }} -{{- end }} \ No newline at end of file +{{- end }} diff --git a/discovery-handler-modules/coap-discovery-handler/.gitignore b/discovery-handler-modules/coap-discovery-handler/.gitignore new file mode 100644 index 000000000..89c0bb339 --- /dev/null +++ b/discovery-handler-modules/coap-discovery-handler/.gitignore @@ -0,0 +1,5 @@ +/target +**/*.rs.bk +Cargo.lock +bin/ +pkg/ \ No newline at end of file diff --git a/discovery-handler-modules/coap-discovery-handler/Cargo.toml b/discovery-handler-modules/coap-discovery-handler/Cargo.toml new file mode 100644 index 000000000..7975d55a2 --- /dev/null +++ b/discovery-handler-modules/coap-discovery-handler/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "coap-discovery-handler" +version = "0.6.8" +authors = ["Jiayi Hu "] +edition = "2018" + +[dependencies] +# TODO: Change this to Akri main when the library is merged +akri-discovery-utils = { path = "../../discovery-utils" } +anyhow = "1.0.41" +async-trait = "0.1.0" +coap = { git = "https://github.com/Covertness/coap-rs" } +coap-lite = "0.4.1" +env_logger = "0.8.4" +log = "0.4.14" +serde = "1.0.104" +serde_json = "1.0.45" +serde_derive = "1.0.104" +tokio = { version = "0.2", features = ["rt-threaded", "sync", "time", "stream", "fs", "macros", "uds"] } +tonic = {version = "0.1.0", features = ["tls"] } + +[dev-dependencies] +mockall = "0.9.0" diff --git a/discovery-handler-modules/coap-discovery-handler/Dockerfile.discovery-handler b/discovery-handler-modules/coap-discovery-handler/Dockerfile.discovery-handler new file mode 100644 index 000000000..dc7577ed7 --- /dev/null +++ b/discovery-handler-modules/coap-discovery-handler/Dockerfile.discovery-handler @@ -0,0 +1,20 @@ +FROM amd64/rust:1.47 as build +RUN rustup component add rustfmt --toolchain 1.47.0-x86_64-unknown-linux-gnu +RUN USER=root cargo new --bin dh +WORKDIR /dh +COPY ./Cargo.toml ./Cargo.toml +RUN cargo build --release && \ + rm ./src/*.rs && \ + DEP_PATH=`echo "./target/release/deps/coap-discovery-handler*" | tr - _` && \ + rm $DEP_PATH +COPY ./src ./src +RUN cargo build --release + +FROM amd64/debian:buster-slim +RUN apt-get update && \ + apt-get install -y --no-install-recommends libssl-dev && \ + apt-get clean +COPY --from=build /dh/target/release/coap-discovery-handler /coap-discovery-handler + +ENV RUST_LOG=coap_discovery_handler,akri_shared,akri_discovery_utils,akri_coap +ENTRYPOINT ["/coap-discovery-handler"] diff --git a/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs b/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs new file mode 100644 index 000000000..51300877a --- /dev/null +++ b/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs @@ -0,0 +1,257 @@ +use super::discovery_utils::{parse_link_value, CoAPClient, CoAPClientImpl}; +use akri_discovery_utils::discovery::{ + discovery_handler::{deserialize_discovery_details, DISCOVERED_DEVICES_CHANNEL_CAPACITY}, + v0::{discovery_handler_server::DiscoveryHandler, Device, DiscoverRequest, DiscoverResponse}, + DiscoverStream, +}; +use async_trait::async_trait; +use coap_lite::CoapRequest; +use log::{error, info}; +use std::collections::HashMap; +use std::time::Duration; +use tokio::sync::mpsc; +use tokio::time::delay_for; +use tonic::{Response, Status}; + +// TODO: make this configurable +pub const DISCOVERY_INTERVAL_SECS: u64 = 10; + +pub const COAP_RESOURCE_TYPES_LABEL_ID: &str = "COAP_RESOURCE_TYPES"; +pub const COAP_IP_LABEL_ID: &str = "COAP_IP"; + +/// This defines a query filter. The RFC7252 allows only one filter element. +#[derive(Serialize, Deserialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct QueryFilter { + pub name: String, + pub value: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct CoAPDiscoveryDetails { + pub multicast: bool, + pub multicast_ip_address: String, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub static_ip_addresses: Vec, + pub query_filter: Option, + pub discovery_timeout_seconds: u32, +} + +pub struct DiscoveryHandlerImpl { + register_sender: tokio::sync::mpsc::Sender<()>, +} + +impl DiscoveryHandlerImpl { + pub fn new(register_sender: tokio::sync::mpsc::Sender<()>) -> Self { + DiscoveryHandlerImpl { register_sender } + } +} + +#[async_trait] +impl DiscoveryHandler for DiscoveryHandlerImpl { + type DiscoverStream = DiscoverStream; + async fn discover( + &self, + request: tonic::Request, + ) -> Result, Status> { + let mut register_sender = self.register_sender.clone(); + let discover_request = request.get_ref(); + let (mut discovered_devices_sender, discovered_devices_receiver) = + mpsc::channel(DISCOVERED_DEVICES_CHANNEL_CAPACITY); + let discovery_handler_config: CoAPDiscoveryDetails = + deserialize_discovery_details(&discover_request.discovery_details) + .map_err(|e| tonic::Status::new(tonic::Code::InvalidArgument, format!("{}", e)))?; + + info!("Discovering config {:?}", discovery_handler_config); + + let multicast = discovery_handler_config.multicast; + let static_addrs = discovery_handler_config.static_ip_addresses; + let multicast_addr = discovery_handler_config.multicast_ip_address; + let query_filter = discovery_handler_config.query_filter; + let timeout = + Duration::from_secs(discovery_handler_config.discovery_timeout_seconds as u64); + + tokio::spawn(async move { + loop { + let mut devices: Vec = vec![]; + + // Discover devices via static IPs + for ip_address in &static_addrs { + let coap_client = CoAPClientImpl::new((ip_address.as_str(), 5683)); + let device = discover_endpoint( + &coap_client, + &ip_address, + query_filter.as_ref(), + timeout, + ); + + match device { + Ok(device) => devices.push(device), + Err(e) => { + info!("Discovering endpoint {} went wrong: {}", ip_address, e); + } + } + } + + // Discover devices via multicast + if multicast { + let coap_client = CoAPClientImpl::new((multicast_addr.as_str(), 5683)); + let discovered = + discover_multicast(&coap_client, query_filter.as_ref(), timeout); + + match discovered { + Ok(mut discovered) => { + devices.append(&mut discovered); + } + Err(e) => { + error!("Error while discovering devices via multicast {}", e); + } + } + } + + if let Err(e) = discovered_devices_sender + .send(Ok(DiscoverResponse { devices })) + .await + { + error!( + "discover - for CoAP failed to send discovery response with error {}", + e + ); + register_sender.send(()).await.unwrap(); + break; + } + + delay_for(Duration::from_secs(DISCOVERY_INTERVAL_SECS)).await; + } + }); + + Ok(Response::new(discovered_devices_receiver)) + } +} + +fn discover_endpoint( + coap_client: &impl CoAPClient, + ip_address: &String, + query_filter: Option<&QueryFilter>, + timeout: Duration, +) -> Result { + let endpoint = format!("coap://{}:5683{}", ip_address, build_path(query_filter)); + + info!("Discovering resources on endpoint {}", endpoint); + + let response = coap_client.get_with_timeout(endpoint.as_str(), timeout); + + match response { + Ok(response) => { + let payload = String::from_utf8(response.message.payload) + .expect("Received payload is not a string"); + info!("Device responded with {}", payload); + + let parsed = parse_payload(ip_address, query_filter, &payload); + + match parsed { + Some(result) => Ok(result), + None => Err(anyhow::format_err!( + "Could not find any resource in the parsed payload" + )), + } + } + Err(e) => Err(anyhow::format_err!( + "Error requesting resource discovery to device: {}", + e + )), + } +} + +fn discover_multicast( + coap_client: &impl CoAPClient, + query_filter: Option<&QueryFilter>, + timeout: Duration, +) -> Result, anyhow::Error> { + use std::net::SocketAddr; + + let mut packet: CoapRequest = CoapRequest::new(); + packet.set_path(build_path(query_filter).as_str()); + + coap_client.send_all_coap(&packet, 0)?; + coap_client.set_receive_timeout(Some(timeout))?; + + let mut results = Vec::new(); + + while let Ok((response, src)) = coap_client.receive_from() { + let ip_addr = src.ip().to_string(); + let payload = + String::from_utf8(response.message.payload).expect("Received payload is not a string"); + info!( + "Device {} responded multicast with payload {}", + ip_addr, payload + ); + + let result = parse_payload(&ip_addr, query_filter, &payload); + + if let Some(r) = result { + results.push(r) + } + } + + Ok(results) +} + +fn parse_payload( + ip_address: &String, + query_filter: Option<&QueryFilter>, + payload: &String, +) -> Option { + let mut properties: HashMap = HashMap::new(); + let mut resources = parse_link_value(payload.as_str()); + + // Check the parsed resources because CoAP devices are allowed to ignore query filters + if let Some(qf) = query_filter { + resources = resources + .into_iter() + .filter(|(uri, rtype)| { + let is_uri_okay = qf.name != String::from("href") || *uri == qf.value; + // TODO: support wildcart syntax + let is_type_okay = qf.name != String::from("rt") || *rtype == qf.value; + + is_uri_okay && is_type_okay + }) + .collect(); + } + + // Don't register devices without any resource + if resources.is_empty() { + return None; + } + + let resource_types: Vec = resources + .iter() + .map(|(_uri, rtype)| rtype.clone()) + .collect(); + + properties.insert(COAP_IP_LABEL_ID.to_string(), ip_address.clone()); + properties.insert( + COAP_RESOURCE_TYPES_LABEL_ID.to_string(), + resource_types.join(","), + ); + + for (uri, rtype) in resources { + properties.insert(rtype, uri); + } + + Some(Device { + id: ip_address.clone(), + properties, + mounts: Vec::default(), + device_specs: Vec::default(), + }) +} + +fn build_path(query_filter: Option<&QueryFilter>) -> String { + if let Some(qf) = query_filter { + format!("/well-known/core?{}={}", qf.name, qf.value) + } else { + String::from("/well-known/core") + } +} diff --git a/discovery-handler-modules/coap-discovery-handler/src/discovery_utils.rs b/discovery-handler-modules/coap-discovery-handler/src/discovery_utils.rs new file mode 100644 index 000000000..fd557c557 --- /dev/null +++ b/discovery-handler-modules/coap-discovery-handler/src/discovery_utils.rs @@ -0,0 +1,122 @@ +use coap::CoAPClient as Client; +use coap_lite::{CoapRequest, CoapResponse}; +use log::{debug, info}; +#[cfg(test)] +use mockall::{automock, predicate::*}; +use std::net::{SocketAddr, ToSocketAddrs}; +use std::time::Duration; + +type Result = std::io::Result; + +#[cfg_attr(test, automock)] +pub trait CoAPClient: Sized { + fn get_with_timeout(&self, url: &str, timeout: Duration) -> Result; + fn send_all_coap(&self, request: &CoapRequest, segment: u8) -> Result<()>; + fn set_receive_timeout(&self, dur: Option) -> Result<()>; + fn receive_from(&self) -> Result<(CoapResponse, SocketAddr)>; +} + +pub struct CoAPClientImpl { + client: Client, +} + +impl CoAPClientImpl { + pub fn new(addr: A) -> Self { + CoAPClientImpl { + client: Client::new(addr).unwrap(), + } + } +} + +impl CoAPClient for CoAPClientImpl { + fn get_with_timeout(&self, url: &str, timeout: Duration) -> Result { + Client::get_with_timeout(url, timeout) + } + + fn send_all_coap(&self, request: &CoapRequest, segment: u8) -> Result<()> { + self.client.send_all_coap(request, segment) + } + + fn set_receive_timeout(&self, dur: Option) -> Result<()> { + self.client.set_receive_timeout(dur) + } + + fn receive_from(&self) -> Result<(CoapResponse, SocketAddr)> { + self.client.receive_from() + } +} + +pub struct CoREResource { + uri: String, + interface: Option, + rtype: Option, +} + +impl CoREResource { + fn new(uri: String) -> CoREResource { + CoREResource { + uri, + interface: None, + rtype: None, + } + } +} + +pub fn parse_link_value(link_value: &str) -> Vec<(String, String)> { + use coap_lite::link_format::LinkFormatParser; + + let mut parser = LinkFormatParser::new(link_value); + let mut resources: Vec<(String, String)> = vec![]; + + while let Some(Ok((uri, mut attr_it))) = parser.next() { + debug!("Found CoAP resource {}", uri); + let mut resource = CoREResource::new(uri.to_string()); + + while let Some((attr, value)) = attr_it + .next() + .map(|(name, unquote)| (name, unquote.to_string())) + { + debug!("attr {} value {}", attr, value); + + match attr { + "rt" => resource.rtype = Some(value), + "if" if value.as_str() == "sensor" => { + // Only "sensor" interface is supported for now + resource.interface = Some(value) + } + _ => { + // Other attributes are not supported yet + } + } + } + + if resource.interface.is_none() { + // Unsupported interface + continue; + } + + if let Some(rtype) = resource.rtype { + resources.push((resource.uri, rtype)); + } + } + + info!("Parsed resources {:?}", resources); + + resources +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_resources() { + let link = r#";rt="oic.r.temperature";if="sensor""#; + let resources = parse_link_value(link); + + let (uri, rtype) = resources.get(0).expect("No resources parsed"); + + assert_eq!(rtype, "oic.r.temperature"); + assert_eq!(uri, "/sensors/temp"); + } +} diff --git a/discovery-handler-modules/coap-discovery-handler/src/main.rs b/discovery-handler-modules/coap-discovery-handler/src/main.rs new file mode 100644 index 000000000..5d1fd4658 --- /dev/null +++ b/discovery-handler-modules/coap-discovery-handler/src/main.rs @@ -0,0 +1,31 @@ +mod discovery_handler; +mod discovery_utils; + +#[macro_use] +extern crate serde_derive; + +use akri_discovery_utils::discovery::discovery_handler::run_discovery_handler; +use discovery_handler::DiscoveryHandlerImpl; + +#[tokio::main] +async fn main() -> Result<(), Box> { + env_logger::try_init()?; + + // Specify the name of this DiscoveryHandler. A discovery handler is usually, but not necessarily, identified by + // the protocol it uses. + let name = "coap"; + // Specify whether the devices discovered by this discovery handler are locally attached (or embedded) to nodes or are + // network based and usable/sharable by multiple nodes. + let shared = false; + // A DiscoveryHandler must handle the Agent dropping a connection due to a Configuration that utilizes this + // DiscoveryHandler being deleted or the Agent erroring. It is impossible to determine the cause of the + // disconnection, so in case the Agent did error out, the Discovery Handler should try to re-register. + let (register_sender, register_receiver) = tokio::sync::mpsc::channel(2); + // Create a DiscoveryHandler + let discovery_handler = DiscoveryHandlerImpl::new(register_sender); + // This function will register the DiscoveryHandler with the Agent's registration socket + // and serve its discover service over UDS at the socket path + // `format!("{}/{}.sock"), env::var("DISCOVERY_HANDLERS_DIRECTORY"), name)`. + run_discovery_handler(discovery_handler, register_receiver, name, shared).await?; + Ok(()) +} diff --git a/samples/brokers/coap-broker/Cargo.toml b/samples/brokers/coap-broker/Cargo.toml new file mode 100644 index 000000000..066cbb757 --- /dev/null +++ b/samples/brokers/coap-broker/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "coap-broker" +version = "0.1.0" +authors = ["Jiayi Hu "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +akri-shared = { path = "../../../shared" } +coap = { git = "https://github.com/Covertness/coap-rs" } +coap-lite = "0.4" +env_logger = "0.8.4" +log = "0.4.14" +tokio = { version = "1", features = ["full"] } +tokio-stream = "0.1.3" +warp = "0.3" +futures = "0.3" +anyhow = "1.0.38" diff --git a/samples/brokers/coap-broker/src/http_coap.rs b/samples/brokers/coap-broker/src/http_coap.rs new file mode 100644 index 000000000..ca57fee16 --- /dev/null +++ b/samples/brokers/coap-broker/src/http_coap.rs @@ -0,0 +1,71 @@ +use coap_lite::{ContentFormat, MessageClass, Packet}; +use warp::hyper::{Response, StatusCode}; + +pub fn coap_to_http(packet: Packet) -> Response> { + let coap_status_code = packet.header.code; + let content_format = match packet.get_content_format() { + Some(c) => c, + None => ContentFormat::ApplicationOctetStream, + }; + let content_type = content_format_to_content_type(content_format); + + let http_status_code = coap_code_to_http_code(coap_status_code); + let http_status = StatusCode::from_u16(http_status_code).unwrap(); + + // TODO: Convert and copy over headers from CoAP to HTTP + Response::builder() + .status(http_status) + .header("Content-Type", content_type) + .body(packet.payload) + .unwrap() +} + +/// Converts a CoAP status code to HTTP status code. The CoAP status code field is described in +/// RFC 7252 Section 3. +/// +/// Put simply, a CoAP status code is 8bits, where the first 3 bits indicate the class and the +/// remaining 5 bits the type. For instance a status code 0x84 is 0b100_01000, which is 4_04 aka +/// NotFound in HTTP :) +fn coap_code_to_http_code(coap_code: MessageClass) -> u16 { + let binary_code = u8::from(coap_code); + let class = binary_code >> 5; + let class_type = binary_code & 0b00011111; + + let http_code = (class as u16) * 100 + (class_type as u16); + + http_code +} + +fn content_format_to_content_type(content_format: ContentFormat) -> String { + match content_format { + ContentFormat::TextPlain => "text/plain".to_string(), + ContentFormat::ApplicationLinkFormat => "application/link-format".to_string(), + ContentFormat::ApplicationXML => "application/xml".to_string(), + ContentFormat::ApplicationOctetStream => "application/octet-stream".to_string(), + ContentFormat::ApplicationEXI => "application/exi".to_string(), + ContentFormat::ApplicationJSON => "application/json".to_string(), + ContentFormat::ApplicationCBOR => "application/cbor".to_string(), + ContentFormat::ApplicationSenmlJSON => "application/senml+json".to_string(), + ContentFormat::ApplicationSensmlJSON => "application/sensml+json".to_string(), + ContentFormat::ApplicationSenmlCBOR => "application/senml+cbor".to_string(), + ContentFormat::ApplicationSensmlCBOR => "application/sensml+cbor".to_string(), + ContentFormat::ApplicationSenmlExi => "application/senml+exi".to_string(), + ContentFormat::ApplicationSensmlExi => "application/sensml+exi".to_string(), + ContentFormat::ApplicationSenmlXML => "application/senml+xml".to_string(), + ContentFormat::ApplicationSensmlXML => "application/sensml+xml".to_string(), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use coap_lite::{MessageClass, ResponseType}; + + #[test] + fn test_status_code_conversion() { + let coap_status = MessageClass::Response(ResponseType::NotFound); + let http_status = coap_code_to_http_code(coap_status); + + assert_eq!(http_status, 404); + } +} diff --git a/samples/brokers/coap-broker/src/main.rs b/samples/brokers/coap-broker/src/main.rs new file mode 100644 index 000000000..9cd4af940 --- /dev/null +++ b/samples/brokers/coap-broker/src/main.rs @@ -0,0 +1,296 @@ +mod http_coap; + +use akri_shared::os::env_var::{ActualEnvVarQuery, EnvVarQuery}; +use coap::CoAPClient; +use coap_lite::{ContentFormat, MessageClass, Packet, ResponseType}; +use futures::{FutureExt, SinkExt, StreamExt}; +use http_coap::coap_to_http; +use log::{debug, info}; +use std::collections::HashMap; +use std::convert::Infallible; +use std::sync::atomic::{AtomicU16, Ordering}; +use std::sync::{Arc, Mutex}; +use std::time::Duration; +use tokio_stream::wrappers::UnboundedReceiverStream; +use warp::hyper::{Response, StatusCode}; +use warp::path::FullPath; +use warp::ws::Message; +use warp::{Filter, Reply}; + +static CLIENT_COUNTER: AtomicU16 = AtomicU16::new(0); + +fn get_client_id() -> u16 { + CLIENT_COUNTER.fetch_add(1, Ordering::Relaxed) +} + +pub const COAP_RESOURCE_TYPES_LABEL_ID: &str = "COAP_RESOURCE_TYPES"; +pub const COAP_IP_LABEL_ID: &str = "COAP_IP"; + +async fn handle_health() -> Result { + Ok(String::from("Healthy")) +} + +async fn handle_proxy(req: FullPath, state: Arc) -> Result { + let path = req.as_str(); + let ip_address = state.ip_address.clone(); + let resource_uris = state.resource_uris.clone(); + let endpoint = format!("coap://{}:5683{}", ip_address, path); + info!("Proxing request to {}", endpoint); + + if !resource_uris.contains(&path.to_string()) { + let response = Response::builder() + .status(StatusCode::NOT_FOUND) + .body(vec![]) + .unwrap(); + + return Ok(response); + } + + // TODO: should some HTTP headers to set or copied to the CoAP request? E.g. 'Forwarded' + let response = CoAPClient::get_with_timeout(endpoint.as_str(), Duration::from_secs(5)); + + match response { + Ok(response) => { + let coap_status_code = response.message.header.code.clone(); + let proxy_res = coap_to_http(response.message.clone()); + + // Save the response to the cache only if the response is 205 Content + // See RFC 7252 Ch. 5.9 for cachable responses. + if coap_status_code == MessageClass::Response(ResponseType::Content) { + debug!("Saving response of {} to cache", path.clone()); + + let mut cache = state.cache.lock().unwrap(); + cache.insert(path.to_string(), response.message.clone()); + } + + Ok(proxy_res) + } + Err(e) => { + info!("Error while trying to request the device {}", e); + + let cache = state.cache.lock().unwrap(); + let cached_packet = cache.get(&path.to_string()); + + match cached_packet { + Some(packet) => { + debug!("Found response in the cache"); + let response = coap_to_http(packet.clone()); + + Ok(response) + } + None => { + let response = Response::builder() + .status(StatusCode::SERVICE_UNAVAILABLE) + .body(e.to_string().into_bytes()) + .unwrap(); + + Ok(response) + } + } + } + } +} + +async fn handle_stream( + req: FullPath, + state: Arc, + websocket: warp::ws::WebSocket, +) -> anyhow::Result<()> { + let path = req.as_str().to_string(); + let ip_address = state.ip_address.clone(); + let addr = format!("{}:5683", ip_address); + let resource_uris = state.resource_uris.clone(); + info!("Streaming from {}", addr); + + let mut client = CoAPClient::new(addr) + .map_err(|e| anyhow::anyhow!("Invalid client address while creating the client: {}", e))?; + let client_id = get_client_id(); + + let (mut ws_tx, mut ws_rx) = websocket.split(); + let (coap_tx, coap_rx) = tokio::sync::mpsc::unbounded_channel(); + let coap_rx_stream = UnboundedReceiverStream::new(coap_rx); + + if !resource_uris.contains(&path) { + let message = Message::close_with(StatusCode::NOT_FOUND, "Not found"); + ws_tx + .send(message) + .await + .map_err(|e| anyhow::anyhow!("Error sending the close message: {}", e))?; + ws_tx + .close() + .await + .map_err(|e| anyhow::anyhow!("Error closing the websocket connection: {}", e))?; + return Ok(()); + } + + tokio::task::spawn(coap_rx_stream.forward(ws_tx).map(|result| { + if let Err(e) = result { + log::error!("websocket send error: {}", e); + } + })); + + let state_clone = state.clone(); + let coap_tx_clone = coap_tx.clone(); + + tokio::task::spawn(async move { + while let Some(message) = ws_rx.next().await { + match message { + Ok(msg) => { + if msg.is_close() { + coap_tx_clone.send(Ok(Message::close())).unwrap(); + + unobserve(state_clone.clone(), client_id); + } + } + Err(e) => { + log::error!("Websocket received an error: {}", e); + break; + } + } + } + }); + + let observe_state = state.clone(); + + client + .observe_with_timeout( + path.as_str(), + move |packet| { + let content_format = match packet.get_content_format() { + Some(c) => c, + None => ContentFormat::ApplicationOctetStream, + }; + let message = match content_format { + ContentFormat::TextPlain | ContentFormat::ApplicationJSON => { + let content = String::from_utf8_lossy(&packet.payload[..]); + + Message::text(content) + } + _ => Message::binary(packet.payload), + }; + + match coap_tx.send(Ok(message)) { + Ok(()) => {} + Err(e) => { + log::error!("Error sending the CoAP message: {}", e); + unobserve(observe_state.clone(), client_id); + } + } + }, + Duration::from_secs(5), + ) + .map_err(|e| anyhow::anyhow!("Error observing the request: {}", e))?; + + let mut clients = state.clients.lock().unwrap(); + clients.insert(client_id, client); + + Ok(()) +} + +fn unobserve(state: Arc, client_id: u16) { + // Unsubscription must be done in a new OS thread because it internally joins on the thread handle, + // which would throw if `unsubscribe` is called within the `observe_with_timeout` closure + std::thread::spawn(move || { + let mut clients = state.clients.lock().unwrap(); + let client = clients.remove(&client_id); + + if let Some(mut client) = client { + client.unobserve(); + } + }); +} + +struct AppState { + ip_address: String, + resource_uris: Vec, + // The CoAP packet is saved instead of the HTTP response because the latter doesn't implement + // Clone and cannot thus returned multiple times + cache: Mutex>, + clients: Mutex>, +} + +#[tokio::main] +async fn main() { + env_logger::init(); + + let env_var_query = ActualEnvVarQuery {}; + let device_ip = get_device_ip(&env_var_query); + let resource_types = get_resources_types(&env_var_query); + let resource_uris: Vec = resource_types + .iter() + .map(|rtype| get_resource_uri(&env_var_query, rtype)) + .collect(); + + info!( + "Found device IP {} with resource types {:?}", + device_ip, resource_types + ); + + let state = Arc::new(AppState { + ip_address: device_ip, + resource_uris, + cache: Mutex::new(HashMap::new()), + clients: Mutex::new(HashMap::new()), + }); + + let health = warp::get() + .and(warp::path("healthz")) + .and_then(handle_health); + let proxy = warp::get() + .and(warp::path::full()) + .and(with_state(state.clone())) + .and_then(handle_proxy); + let stream = warp::get() + .and(warp::path::full()) + .and(with_state(state.clone())) + .and(warp::ws()) + .map(|path: FullPath, state: Arc, ws: warp::ws::Ws| { + ws.on_upgrade(move |websocket| async { + match handle_stream(path, state, websocket).await { + Ok(()) => {} + Err(e) => { + log::error!("Error handling the websocket stream: {}", e); + } + } + }) + }); + + let routes = health.or(stream).or(proxy).with(warp::log("api")); + + warp::serve(routes).run(([0, 0, 0, 0], 8083)).await; +} + +fn with_state( + state: Arc, +) -> impl warp::Filter,), Error = Infallible> + Clone { + warp::any().map(move || state.clone()) +} + +fn get_device_ip(env_var_query: &impl EnvVarQuery) -> String { + let ip_address = env_var_query + .get_env_var(COAP_IP_LABEL_ID) + .expect("Device IP address not set in environment variable"); + + ip_address +} + +fn get_resources_types(env_var_query: &impl EnvVarQuery) -> Vec { + let types_string: String = env_var_query + .get_env_var(COAP_RESOURCE_TYPES_LABEL_ID) + .expect("Device resource types not set in environment variable"); + let resource_types: Vec = types_string.split(",").map(|s| s.to_string()).collect(); + + resource_types +} + +fn get_resource_uri(env_var_query: &impl EnvVarQuery, resource_type: &str) -> String { + let value = env_var_query.get_env_var(resource_type).expect( + format!( + "Device resource URI for type {} not set in environment variable", + resource_type + ) + .as_str(), + ); + + value +} From 21d676b7f9a155447df27bb5c1e191c169643877 Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Thu, 1 Jul 2021 18:14:01 +0200 Subject: [PATCH 02/15] Integrate CoAP discovery handler to the build system --- .dockerignore | 5 ++++- .github/workflows/build-discovery-handlers.yml | 2 ++ .github/workflows/run-test-cases.yml | 2 +- build/akri-containers.mk | 7 ++++--- build/containers/Dockerfile.coap-discovery | 18 ++++++++++++++++++ version.sh | 8 ++++---- 6 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 build/containers/Dockerfile.coap-discovery diff --git a/.dockerignore b/.dockerignore index 2cf322834..8b2bcbd4d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -44,6 +44,7 @@ !target/x86_64-unknown-linux-gnu/debug/webhook-configuration !target/x86_64-unknown-linux-gnu/release/webhook-configuration !target/x86_64-unknown-linux-gnu/release/udev-discovery-handler +!target/x86_64-unknown-linux-gnu/release/coap-discovery-handler !target/x86_64-unknown-linux-gnu/release/debug-echo-discovery-handler !target/x86_64-unknown-linux-gnu/release/onvif-discovery-handler !target/x86_64-unknown-linux-gnu/release/opcua-discovery-handler @@ -58,6 +59,7 @@ !target/aarch64-unknown-linux-gnu/debug/webhook-configuration !target/aarch64-unknown-linux-gnu/release/webhook-configuration !target/aarch64-unknown-linux-gnu/release/udev-discovery-handler +!target/aarch64-unknown-linux-gnu/release/coap-discovery-handler !target/aarch64-unknown-linux-gnu/release/debug-echo-discovery-handler !target/aarch64-unknown-linux-gnu/release/onvif-discovery-handler !target/aarch64-unknown-linux-gnu/release/opcua-discovery-handler @@ -72,6 +74,7 @@ !target/armv7-unknown-linux-gnueabihf/debug/webhook-configuration !target/armv7-unknown-linux-gnueabihf/release/webhook-configuration !target/armv7-unknown-linux-gnueabihf/release/udev-discovery-handler +!target/armv7-unknown-linux-gnueabihf/release/coap-discovery-handler !target/armv7-unknown-linux-gnueabihf/release/debug-echo-discovery-handler !target/armv7-unknown-linux-gnueabihf/release/onvif-discovery-handler !target/armv7-unknown-linux-gnueabihf/release/opcua-discovery-handler @@ -80,4 +83,4 @@ !Cross.toml # Container image license to be copied into every container -!build/container-images-legal-notice.md \ No newline at end of file +!build/container-images-legal-notice.md diff --git a/.github/workflows/build-discovery-handlers.yml b/.github/workflows/build-discovery-handlers.yml index faf44b5ca..a10964bab 100644 --- a/.github/workflows/build-discovery-handlers.yml +++ b/.github/workflows/build-discovery-handlers.yml @@ -22,6 +22,7 @@ jobs: - arm32v7 - amd64 akri-component: + - coap-discovery - debug-echo-discovery - udev-discovery - onvif-discovery @@ -77,6 +78,7 @@ jobs: strategy: matrix: akri-component: + - coap-discovery - debug-echo-discovery - udev-discovery - onvif-discovery diff --git a/.github/workflows/run-test-cases.yml b/.github/workflows/run-test-cases.yml index f98dbff29..7aedb651f 100644 --- a/.github/workflows/run-test-cases.yml +++ b/.github/workflows/run-test-cases.yml @@ -62,7 +62,7 @@ jobs: BUILD_ARM64: 0 BUILD_SLIM_AGENT: 0 AGENT_FEATURES: "agent-full" - PACKAGES_TO_EXCLUDE: "akri-udev akri-onvif akri-opcua udev-video-broker debug-echo-discovery-handler onvif-discovery-handler opcua-discovery-handler udev-discovery-handler" + PACKAGES_TO_EXCLUDE: "akri-udev akri-onvif akri-opcua udev-video-broker coap-discovery-handler debug-echo-discovery-handler onvif-discovery-handler opcua-discovery-handler udev-discovery-handler" PREFIX: ghcr.io/deislabs/akri LABEL_PREFIX: pr CARGO_INCREMENTAL: 0 diff --git a/build/akri-containers.mk b/build/akri-containers.mk index 041058fc5..afc59c211 100644 --- a/build/akri-containers.mk +++ b/build/akri-containers.mk @@ -39,8 +39,8 @@ install-cross: # # To make all platforms: `make akri` # To make specific platforms: `BUILD_AMD64=1 BUILD_ARM32=0 BUILD_ARM64=1 make akri` -# To make single component: `make akri-[controller|agent|udev|onvif|streaming|opcua-monitoring|anomaly-detection|webhook-configuration|debug-echo-discovery|udev-discovery|onvif-discovery|opcua-discovery]` -# To make specific platforms: `BUILD_AMD64=1 BUILD_ARM32=0 BUILD_ARM64=1 make akri-[controller|agent|udev|onvif|streaming|opcua-monitoring|anomaly-detection|webhook-configuration|debug-echo-discovery|udev-discovery|onvif-discovery|opcua-discovery]` +# To make single component: `make akri-[controller|agent|udev|onvif|streaming|opcua-monitoring|anomaly-detection|webhook-configuration|coap-discovery|debug-echo-discovery|udev-discovery|onvif-discovery|opcua-discovery]` +# To make specific platforms: `BUILD_AMD64=1 BUILD_ARM32=0 BUILD_ARM64=1 make akri-[controller|agent|udev|onvif|streaming|opcua-monitoring|anomaly-detection|webhook-configuration|coap-discovery|debug-echo-discovery|udev-discovery|onvif-discovery|opcua-discovery]` # To make an agent with embedded discovery handlers (on all platforms): `FULL_AGENT_EXECUTABLE_NAME=agent AGENT_FEATURES="agent-full onvif-feat opcua-feat udev-feat" make akri-agent` # To make a slim agent without any embedded discovery handlers: `BUILD_SLIM_AGENT=1 make akri-agent` # To make a slim and full Agent, with full agent executable renamed agent-full: `AGENT_FEATURES="agent-full onvif-feat opcua-feat udev-feat" BUILD_SLIM_AGENT=1 make akri-agent` @@ -48,7 +48,7 @@ install-cross: .PHONY: akri akri: akri-build akri-docker-all akri-build: install-cross akri-cross-build -akri-docker-all: akri-docker-controller akri-docker-agent akri-docker-udev akri-docker-onvif akri-docker-streaming akri-docker-opcua-monitoring akri-docker-anomaly-detection akri-docker-webhook-configuration akri-docker-debug-echo-discovery akri-docker-onvif-discovery akri-docker-opcua-discovery akri-docker-udev-discovery +akri-docker-all: akri-docker-controller akri-docker-agent akri-docker-udev akri-docker-onvif akri-docker-streaming akri-docker-opcua-monitoring akri-docker-anomaly-detection akri-docker-webhook-configuration akri-docker-coap-discovery akri-docker-debug-echo-discovery akri-docker-onvif-discovery akri-docker-opcua-discovery akri-docker-udev-discovery akri-docker-coap-discovery akri-cross-build: akri-cross-build-amd64 akri-cross-build-arm32 akri-cross-build-arm64 akri-cross-build-amd64: @@ -88,6 +88,7 @@ $(eval $(call add_rust_targets,agent,agent)) $(eval $(call add_rust_targets,agent-full,agent-full)) $(eval $(call add_rust_targets,udev,udev-video-broker)) $(eval $(call add_rust_targets,webhook-configuration,webhook-configuration)) +$(eval $(call add_rust_targets,coap-discovery,coap-discovery)) $(eval $(call add_rust_targets,debug-echo-discovery,debug-echo-discovery)) $(eval $(call add_rust_targets,onvif-discovery,onvif-discovery)) $(eval $(call add_rust_targets,opcua-discovery,opcua-discovery)) diff --git a/build/containers/Dockerfile.coap-discovery b/build/containers/Dockerfile.coap-discovery new file mode 100644 index 000000000..da04386b8 --- /dev/null +++ b/build/containers/Dockerfile.coap-discovery @@ -0,0 +1,18 @@ +ARG PLATFORM=amd64 +ARG CROSS_BUILD_TARGET=x86_64-unknown-linux-gnu +FROM ${PLATFORM}/debian:buster-slim +ARG CROSS_BUILD_TARGET +ARG BUILD_TYPE=release +RUN echo "Creating container based on ${PLATFORM}/debian:buster-slim" +RUN echo "Using Rust binaries from ${CROSS_BUILD_TARGET}/${BUILD_TYPE}" + +# Link the container to the Akri repository +LABEL org.opencontainers.image.source https://github.com/deislabs/akri + +# Copy over container legal notice +COPY ./build/container-images-legal-notice.md . + +RUN apt-get update && apt-get install -y --no-install-recommends libssl-dev openssl && apt-get clean +COPY ./target/${CROSS_BUILD_TARGET}/${BUILD_TYPE}/coap-discovery-handler /coap-discovery-handler +ENV RUST_LOG=coap_discovery_handler,akri_shared,akri_discovery_utils,akri_coap +CMD ["./coap-discovery-handler"] diff --git a/version.sh b/version.sh index 165cba006..2b33bee3e 100755 --- a/version.sh +++ b/version.sh @@ -124,7 +124,7 @@ if [ "$CHECK" == "1" ]; then echo " Verified format: $BASEDIR/version.txt" fi - CARGO_FILES="$BASEDIR/shared/Cargo.toml $BASEDIR/agent/Cargo.toml $BASEDIR/controller/Cargo.toml $BASEDIR/samples/brokers/udev-video-broker/Cargo.toml $BASEDIR/webhooks/validating/configuration/Cargo.toml $BASEDIR/discovery-utils/Cargo.toml $BASEDIR/discovery-handlers/debug-echo/Cargo.toml $BASEDIR/discovery-handlers/onvif/Cargo.toml $BASEDIR/discovery-handlers/opcua/Cargo.toml $BASEDIR/discovery-handlers/udev/Cargo.toml $BASEDIR/discovery-handler-modules/debug-echo-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/onvif-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/opcua-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/udev-discovery-handler/Cargo.toml" + CARGO_FILES="$BASEDIR/shared/Cargo.toml $BASEDIR/agent/Cargo.toml $BASEDIR/controller/Cargo.toml $BASEDIR/samples/brokers/udev-video-broker/Cargo.toml $BASEDIR/webhooks/validating/configuration/Cargo.toml $BASEDIR/discovery-utils/Cargo.toml $BASEDIR/discovery-handlers/debug-echo/Cargo.toml $BASEDIR/discovery-handlers/onvif/Cargo.toml $BASEDIR/discovery-handlers/opcua/Cargo.toml $BASEDIR/discovery-handlers/udev/Cargo.toml $BASEDIR/discovery-handler-modules/coap-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/debug-echo-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/onvif-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/opcua-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/udev-discovery-handler/Cargo.toml" TOML_VERSION_PATTERN="^version" TOML_VERSION="\"$(echo $VERSION)\"" for CARGO_FILE in $CARGO_FILES @@ -133,7 +133,7 @@ if [ "$CHECK" == "1" ]; then if [ "$?" -eq "1" ]; then exit 1; fi done - CARGO_LOCK_PROJECTS="controller akri-shared agent controller webhook-configuration udev-video-broker akri-discovery-utils akri-debug-echo akri-udev akri-onvif akri-opcua debug-echo-discovery-handler onvif-discovery-handler udev-discovery-handler opcua-discovery-handler" + CARGO_LOCK_PROJECTS="controller akri-shared agent controller webhook-configuration udev-video-broker akri-discovery-utils akri-debug-echo akri-udev akri-onvif akri-opcua coap-discovery-handler debug-echo-discovery-handler onvif-discovery-handler udev-discovery-handler opcua-discovery-handler" CARGO_LOCK_VERSION="\"$(echo $VERSION)\"" for CARGO_LOCK_PROJECT in $CARGO_LOCK_PROJECTS do @@ -187,7 +187,7 @@ then fi echo "Updating to version: $NEW_VERSION" - CARGO_FILES="$BASEDIR/shared/Cargo.toml $BASEDIR/agent/Cargo.toml $BASEDIR/controller/Cargo.toml $BASEDIR/samples/brokers/udev-video-broker/Cargo.toml $BASEDIR/webhooks/validating/configuration/Cargo.toml $BASEDIR/discovery-utils/Cargo.toml $BASEDIR/discovery-handlers/debug-echo/Cargo.toml $BASEDIR/discovery-handlers/onvif/Cargo.toml $BASEDIR/discovery-handlers/opcua/Cargo.toml $BASEDIR/discovery-handlers/udev/Cargo.toml $BASEDIR/discovery-handler-modules/debug-echo-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/onvif-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/opcua-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/udev-discovery-handler/Cargo.toml" + CARGO_FILES="$BASEDIR/shared/Cargo.toml $BASEDIR/agent/Cargo.toml $BASEDIR/controller/Cargo.toml $BASEDIR/samples/brokers/udev-video-broker/Cargo.toml $BASEDIR/webhooks/validating/configuration/Cargo.toml $BASEDIR/discovery-utils/Cargo.toml $BASEDIR/discovery-handlers/debug-echo/Cargo.toml $BASEDIR/discovery-handlers/onvif/Cargo.toml $BASEDIR/discovery-handlers/opcua/Cargo.toml $BASEDIR/discovery-handlers/udev/Cargo.toml $BASEDIR/discovery-handler-modules/coap-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/debug-echo-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/onvif-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/opcua-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/udev-discovery-handler/Cargo.toml" TOML_VERSION_PATTERN="^version = .*" TOML_VERSION_LINE="version = \"$NEW_VERSION\"" for CARGO_FILE in $CARGO_FILES @@ -196,7 +196,7 @@ then if [ "$?" -eq "1" ]; then exit 1; fi done - CARGO_LOCK_PROJECTS="controller akri-shared agent controller webhook-configuration udev-video-broker akri-discovery-utils akri-debug-echo akri-udev akri-onvif akri-opcua debug-echo-discovery-handler onvif-discovery-handler udev-discovery-handler opcua-discovery-handler" + CARGO_LOCK_PROJECTS="controller akri-shared agent controller webhook-configuration udev-video-broker akri-discovery-utils akri-debug-echo akri-udev akri-onvif akri-opcua coap-discovery-handler debug-echo-discovery-handler onvif-discovery-handler udev-discovery-handler opcua-discovery-handler" CARGO_LOCK_VERSION_PATTERN="^version = .*" CARGO_LOCK_VERSION_LINE="version = \"$NEW_VERSION\"" for CARGO_LOCK_PROJECT in $CARGO_LOCK_PROJECTS From 16dcb726779efe74ec91e8a8d156881cab627865 Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Thu, 1 Jul 2021 18:58:27 +0200 Subject: [PATCH 03/15] Add CoAP proposal documentation --- docs/proposals/coap.md | 79 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 docs/proposals/coap.md diff --git a/docs/proposals/coap.md b/docs/proposals/coap.md new file mode 100644 index 000000000..1707d442c --- /dev/null +++ b/docs/proposals/coap.md @@ -0,0 +1,79 @@ +# [CoAP](https://tools.ietf.org/html/rfc7252) Protocol Implementation + +## Goal + +_From the RFC 6690_: + +The Constrained RESTful Environments (CoRE) realizes the Representational State Transfer (REST) architecture [REST] in a suitable form for the most constrained nodes (e.g., 8-bit microcontrollers with limited memory) and networks (e.g., IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs) [RFC4919]). CoRE is aimed at Machine-to-Machine (M2M) applications such as smart energy and building automation. + +The main function of such a discovery mechanism is to provide Universal Resource Identifiers (URIs, called links) for the resources hosted by the server, complemented by attributes about those resources and possible further link relations. In CoRE, this collection of links is carried as a resource of its own (as opposed to HTTP headers delivered with a specific resource). + +## Discovery Process + +### The standard + +A well-known relative URI `/.well-known/core` is defined as a default entry point for requesting the list of links about resources hosted by a server and thus performing CoRE Resource Discovery. The CoRE protocol is applicable for use with Constrained Application Protocol (CoAP) [COAP](https://tools.ietf.org/html/rfc7252), HTTP, or any other suitable web transfer protocol. + +Resource Discovery can be performed either unicast or multicast. + +When a server's IP address is already known, either a priori or resolved via the Domain Name System (DNS), unicast discovery is performed to locate the entry point to the resource of interest. This specification is achieved using a GET to `/.well-known/core` on the server, which returns a payload in the CoRE Link Format. + +Multicast Resource Discovery is useful when a client needs to locate a resource within a limited scope, and that scope supports IP multicast. A GET request to the appropriate multicast address is made for `/.well-known/core`. To limit the number and size of responses, a query string is recommended with the known attributes. Typically, a resource would be discovered based on its Resource Type and/or Interface Description, along with possible application-specific attributes. + +### With Akri + +The Akri Configuration defines a list of IP addresses to use for resource discovery, implementing thus unicast discovery. Likewise, a multicast IP address can be used for multicast discovery. Both methods can be used at the same time. + +1. The discovery handler sends a `GET /well-known/core` request to the device at `coap://{IP_ADDRESS}:5683`. The standard defines that CoAP devices which intend to support resource discovery must be reachable with the default port `:5683` and expose endpoint `/well-known/core` implementing the CoRE Link Format. +2. The device responds with the list of supported resources. An example of a response in link format is the following: + ``` + ;rt="oic.r.temperature";if="sensor", + ;rt="oic.r.light.brightness";if="sensor" + ``` + + The example is stating that the device has 2 REST resources, `/sensors/temp` and `/sensors/light` which are of type `oic.r.temperature` and `oic.r.light.brightness` respectively. `rt` values are defined in [IANA](https://www.iana.org/assignments/core-parameters/core-parameters.xhtml#rt-link-target-att-value) to have some standardization, although vendor-specific values can be used. Then `if` means that the interface description of the resource is of type `sensor`. Currently, only resources with interface `sensor` are supported by the discovery handler. +3. For each device, the discovery handler returns a result which will have the following properties: + ``` + COAP_IP: 192.168.1.126 + COAP_RESOURCE_TYPES: oic.r.temperature,oic.r.light.brightness + oic.r.light.brightness: /sensors/light + oic.r.temperature: /sensors/temp + ``` + `COAP_IP` and `COAP_RESOURCE_TYPES` are static and available for each Instance. `oic.r.light.brightness` and `oic.r.temperature` are dynamic, based on the discovered resources. By doing so, the cluster can look for a resource (e.g. temperature measurements) by searching for Instances that support the `oic.r.temperature` resource. +4. An Akri Broker is provisioned for each Instance. The Broker has the following environment variables based on the previous properties and can be reached via its associated service: + + ``` + COAP_IP=192.168.1.126 + oic.r.temperature=/sensors/temp + oic.r.light.brightness=/sensors/light + COAP_RESOURCE_TYPES=oic.r.temperature,oic.r.light.brightness + ``` + + The Broker acts as an HTTP-to-CoAP Proxy. It translates RESTful HTTP requests into RESTful CoAP requests and vice versa for the response. "Cross-Protocol Proxying between CoAP and HTTP" is defined in section 10 of RFC 7252. Currently, the Broker forwards only GET requests. + + The Broker is also in an excellent position to cache CoAP responses. "Unlike HTTP, the cacheability of CoAP responses does not depend on the request method, but it depends on the Response Code." Currently, the Broker only caches CoAP responses with status code equal to `2.05 Content`, which is returned if the device is not reachable during the connection. + +## Outstanding Questions + +- Is there a better way to store the discovered resources as Configuration in the cluster? + +The current implementation would need a controller to accept queries about available resources and return the name of the Broker's service which can communicate to the device. The device is listed as a generic `akri.sh/coap-021dd7` resource on the node, which is too generic to be useful by any application. A better label would be `akri.sh/oic.r.temperature-021dd7`, the discovered resource. This would allow using the K8s controller for scheduling pods that need the resource. + +- Is there any way to avoid coupling a CoAP device to any node? + +Akri deploys an agent to each cluster node and each agent has a running CoAP discovery handler. This behaviour results in a single CoAP device being discovered by multiple nodes and listed as multiple virtual CoAP devices. An immediate consequence is that the discovery handlers overflow the device with discovery requests, which causes the device to use more energy and maybe incur in concurrency issues, especially in the case of real-time devices. + +## Feature Requests + +- [x] Support multicast discovery in the discovery handler +- [ ] Support all HTTP verbs in the Broker +- [ ] Handle Header translation in the Broker +- [x] Support Observe [RFC 7641](https://tools.ietf.org/html/rfc7641), which allows the devices to push changes to interested clients. + +## References + +- [CoAP RFC 7252](https://tools.ietf.org/html/rfc7252). +- [CoRE RFC 6690](https://tools.ietf.org/html/rfc6690#:~:text=well-known%2Fcore). +- [CoAP: An Application Protocol for Billions of Tiny Internet Nodes](https://ieeexplore.ieee.org/document/6159216) + +--- From 231cb6093aa5a5de650a223935add6ddb9d5838d Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Thu, 1 Jul 2021 20:49:26 +0200 Subject: [PATCH 04/15] Minor fixes --- deployment/helm/templates/custom-configuration.yaml | 2 +- samples/brokers/coap-broker/src/main.rs | 2 +- shared/src/os/env_var.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/deployment/helm/templates/custom-configuration.yaml b/deployment/helm/templates/custom-configuration.yaml index 7858fac00..ab35c7562 100644 --- a/deployment/helm/templates/custom-configuration.yaml +++ b/deployment/helm/templates/custom-configuration.yaml @@ -10,7 +10,7 @@ spec: multicast: {{ .Values.custom.configuration.discoveryDetails.multicast }} multicastIpAddress: {{ .Values.custom.configuration.discoveryDetails.multicastIpAddress }} staticIpAddresses: - {{ - toYaml .Values.custom.configuration.discoveryDetails.staticIpAddresses | nindent 6 }} + {{- toYaml .Values.custom.configuration.discoveryDetails.staticIpAddresses | nindent 6 }} {{- if .Values.custom.configuration.discoveryDetails.queryFilter }} queryFilter: name: {{ .Values.custom.configuration.discoveryDetails.queryFilter.name }} diff --git a/samples/brokers/coap-broker/src/main.rs b/samples/brokers/coap-broker/src/main.rs index 9cd4af940..70ebaeef4 100644 --- a/samples/brokers/coap-broker/src/main.rs +++ b/samples/brokers/coap-broker/src/main.rs @@ -46,7 +46,7 @@ async fn handle_proxy(req: FullPath, state: Arc) -> Result Result; + fn get_env_var(&self, name: &str) -> Result; } pub struct ActualEnvVarQuery; @@ -21,7 +21,7 @@ impl EnvVarQuery for ActualEnvVarQuery { /// env_query.get_env_var("HOSTNAME") /// ); /// ``` - fn get_env_var(&self, name: &'static str) -> Result { + fn get_env_var(&self, name: &str) -> Result { env::var(name) } } From b5e58d697f603fff9bb24efa285aca92b12b38fb Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Tue, 6 Jul 2021 23:39:11 +0200 Subject: [PATCH 05/15] Avoid using custom-configuration and discovery-handler --- .../helm/templates/coap-configuration.yaml | 73 +++++++++++++ .../templates/coap-discovery-handler.yaml | 46 ++++++++ .../helm/templates/custom-configuration.yaml | 14 +-- .../templates/custom-discovery-handler.yaml | 2 +- deployment/helm/values.yaml | 101 ++++++++++++++++++ deployment/values.yaml | 19 ++++ 6 files changed, 241 insertions(+), 14 deletions(-) create mode 100644 deployment/helm/templates/coap-configuration.yaml create mode 100644 deployment/helm/templates/coap-discovery-handler.yaml create mode 100644 deployment/values.yaml diff --git a/deployment/helm/templates/coap-configuration.yaml b/deployment/helm/templates/coap-configuration.yaml new file mode 100644 index 000000000..fa191e1e2 --- /dev/null +++ b/deployment/helm/templates/coap-configuration.yaml @@ -0,0 +1,73 @@ +{{- if .Values.coap.configuration.enabled }} +apiVersion: {{ printf "%s/%s" .Values.crds.group .Values.crds.version }} +kind: Configuration +metadata: + name: {{ .Values.coap.configuration.name }} +spec: + discoveryHandler: + name: {{ required "A custom.configuration.discoveryHandlerName is required." .Values.coap.configuration.discoveryHandlerName }} + discoveryDetails: |+ + multicast: {{ .Values.coap.configuration.discoveryDetails.multicast }} + multicastIpAddress: {{ .Values.coap.configuration.discoveryDetails.multicastIpAddress }} + staticIpAddresses: + {{- toYaml .Values.coap.configuration.discoveryDetails.staticIpAddresses | nindent 6 }} + {{- if .Values.coap.configuration.discoveryDetails.queryFilter }} + queryFilter: + name: {{ .Values.coap.configuration.discoveryDetails.queryFilter.name }} + value: {{ .Values.coap.configuration.discoveryDetails.queryFilter.value }} + {{- else }} + queryFilter: null + {{- end }} + discoveryTimeoutSeconds: {{ .Values.coap.configuration.discoveryDetails.discoveryTimeoutSeconds }} + {{- if .Values.coap.configuration.brokerPod.image.repository }} + brokerPodSpec: + containers: + - name: {{ .Values.coap.configuration.name }}-broker + image: {{ printf "%s:%s" .Values.coap.configuration.brokerPod.image.repository .Values.coap.configuration.brokerPod.image.tag | quote }} + {{- with .Values.coap.configuration.pullPolicy }} + imagePullPolicy: {{ . }} + {{- end }} + resources: + requests: + {{`"{{PLACEHOLDER}}"`}} : "1" + memory: {{ .Values.coap.configuration.brokerPod.resources.memoryRequest }} + cpu: {{ .Values.coap.configuration.brokerPod.resources.cpuRequest }} + limits: + {{`"{{PLACEHOLDER}}"`}} : "1" + memory: {{ .Values.coap.configuration.brokerPod.resources.memoryLimit }} + cpu: {{ .Values.coap.configuration.brokerPod.resources.cpuLimit }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} + {{- if .Values.coap.configuration.brokerPod.image.repository }} + {{- if .Values.coap.configuration.createInstanceServices }} + instanceServiceSpec: + type: {{ .Values.coap.configuration.instanceService.type }} + ports: + - name: {{ .Values.coap.configuration.instanceService.name }} + port: {{ .Values.coap.configuration.instanceService.port }} + protocol: {{ .Values.coap.configuration.instanceService.protocol }} + targetPort: {{ .Values.coap.configuration.instanceService.targetPort }} + {{- end }} + {{- if .Values.coap.configuration.createConfigurationService }} + configurationServiceSpec: + type: {{ .Values.coap.configuration.configurationService.type }} + ports: + - name: {{ .Values.coap.configuration.configurationService.name }} + port: {{ .Values.coap.configuration.configurationService.port }} + protocol: {{ .Values.coap.configuration.configurationService.protocol }} + targetPort: {{ .Values.coap.configuration.configurationService.port }} + {{- end }} + {{- end }} + {{- if .Values.coap.configuration.brokerProperties }} + brokerProperties: + {{- range $key, $val := .Values.coap.configuration.brokerProperties }} + {{- $key | nindent 4 }}: {{ $val | quote }} + {{- end }} + {{- else }} + brokerProperties: {} + {{- end }} + capacity: {{ .Values.coap.configuration.capacity }} +{{- end }} diff --git a/deployment/helm/templates/coap-discovery-handler.yaml b/deployment/helm/templates/coap-discovery-handler.yaml new file mode 100644 index 000000000..b98bf94f3 --- /dev/null +++ b/deployment/helm/templates/coap-discovery-handler.yaml @@ -0,0 +1,46 @@ +{{- if .Values.coap.discovery.enabled }} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: akri-coap-discovery-daemonset +spec: + selector: + matchLabels: + name: akri-coap-discovery + template: + metadata: + labels: + name: akri-coap-discovery + spec: + containers: + - name: akri-coap-discovery + image: {{ printf "%s:%s" (required "A coap.discovery.image.repository is required." .Values.coap.discovery.image.repository) .Values.coap.discovery.image.tag | quote }} + {{- with .Values.coap.discovery.image.pullPolicy }} + imagePullPolicy: {{ . }} + {{- end}} + resources: + requests: + memory: {{ .Values.coap.discovery.resources.memoryRequest }} + cpu: {{ .Values.coap.discovery.resources.cpuRequest }} + limits: + memory: {{ .Values.coap.discovery.resources.memoryLimit }} + cpu: {{ .Values.coap.discovery.resources.cpuLimit }} + env: + - name: DISCOVERY_HANDLERS_DIRECTORY + value: /var/lib/akri + volumeMounts: + - name: discovery-handlers + mountPath: /var/lib/akri + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.coap.discovery.nodeSelectors }} + nodeSelector: + {{- toYaml .Values.coap.discovery.nodeSelectors | nindent 8 }} + {{- end }} + volumes: + - name: discovery-handlers + hostPath: + path: {{ .Values.agent.host.discoveryHandlers }} +{{- end }} diff --git a/deployment/helm/templates/custom-configuration.yaml b/deployment/helm/templates/custom-configuration.yaml index ab35c7562..fc60289ca 100644 --- a/deployment/helm/templates/custom-configuration.yaml +++ b/deployment/helm/templates/custom-configuration.yaml @@ -6,19 +6,7 @@ metadata: spec: discoveryHandler: name: {{ required "A custom.configuration.discoveryHandlerName is required." .Values.custom.configuration.discoveryHandlerName }} - discoveryDetails: |+ - multicast: {{ .Values.custom.configuration.discoveryDetails.multicast }} - multicastIpAddress: {{ .Values.custom.configuration.discoveryDetails.multicastIpAddress }} - staticIpAddresses: - {{- toYaml .Values.custom.configuration.discoveryDetails.staticIpAddresses | nindent 6 }} - {{- if .Values.custom.configuration.discoveryDetails.queryFilter }} - queryFilter: - name: {{ .Values.custom.configuration.discoveryDetails.queryFilter.name }} - value: {{ .Values.custom.configuration.discoveryDetails.queryFilter.value }} - {{- else }} - queryFilter: null - {{- end }} - discoveryTimeoutSeconds: {{ .Values.custom.configuration.discoveryDetails.discoveryTimeoutSeconds }} + discoveryDetails: {{ .Values.custom.configuration.discoveryDetails }} {{- if .Values.custom.configuration.brokerPod.image.repository }} brokerPodSpec: containers: diff --git a/deployment/helm/templates/custom-discovery-handler.yaml b/deployment/helm/templates/custom-discovery-handler.yaml index f879c1b67..b15a1cf9e 100644 --- a/deployment/helm/templates/custom-discovery-handler.yaml +++ b/deployment/helm/templates/custom-discovery-handler.yaml @@ -43,4 +43,4 @@ spec: - name: discovery-handlers hostPath: path: {{ .Values.agent.host.discoveryHandlers }} -{{- end }} \ No newline at end of file +{{- end }} diff --git a/deployment/helm/values.yaml b/deployment/helm/values.yaml index c9a1555a2..2f6ea64a5 100644 --- a/deployment/helm/values.yaml +++ b/deployment/helm/values.yaml @@ -313,6 +313,107 @@ debugEcho: # cpuLimit defines the maximum amount of CPU this Pod can consume. cpuLimit: 26m +coap: + configuration: + # enabled defines whether to load a coap configuration + enabled: false + # name is the Kubernetes resource name that will be created for this + # coap configuration + name: akri-coap + # brokerProperties is a map of properties that will be passed to any instances + # created as a result of applying this coap configuration + brokerProperties: {} + # capacity is the capacity for any instances created as a result of + # applying this coap configuration + capacity: 1 + discoveryDetails: + multicast: true + multicastIpAddress: 224.0.1.187 + staticIpAddresses: [] + queryFilter: {} + discoveryTimeoutSeconds: 10 + brokerPod: + # container used by coap + image: + # repository is the coap broker container reference + repository: eu.gcr.io/fedra-301320/coap-core-broker + # tag is the coap broker image tag + tag: v0.1.17-20210227_235612 + # pullPolicy is the coap pull policy + pullPolicy: "" + resources: + # memoryRequest defines the minimum amount of RAM that must be available to this Pod + # for it to be scheduled by the Kubernetes Scheduler + memoryRequest: 10Mi + # cpuRequest defines the minimum amount of CPU that must be available to this Pod + # for it to be scheduled by the Kubernetes Scheduler + cpuRequest: 10m + # memoryLimit defines the maximum amount of RAM this Pod can consume. + memoryLimit: 200Mi + # cpuLimit defines the maximum amount of CPU this Pod can consume. + cpuLimit: 0.5 + # createInstanceServices is specified if a service should automatically be + # created for each broker pod + createInstanceServices: true + instanceService: + # name is the description of the instance service + name: akri-coap-foo-instance-service + # type is the service type of the instance service + type: ClusterIP + # port is the service port of the instance service + port: 6052 + # targetPort is the service targetPort of the instance service + targetPort: 6052 + # protocol is the service protocol of the instance service + protocol: TCP + # createConfigurationService is specified if a single service should automatically be + # created for all broker pods of a Configuration + createConfigurationService: true + configurationService: + # name is the description of the configuration service + name: akri-coap-configuration-service + # type is the service type of the instance service + type: ClusterIP + # port is the service port of the instance service + port: 6052 + # targetPort is the service targetPort of the instance service + targetPort: 6052 + # protocol is the service protocol of the instance service + protocol: TCP + # discovery defines a set of values for a coap discovery handler DaemonSet + discovery: + # enabled defines whether discovery handler pods will be deployed in a slim Agent scenario + enabled: false + name: coap + image: + # repository is the container reference + repository: ghcr.io/deislabs/akri/coap-discovery + # tag is the container tag + # coap-configuration.yaml will default to v(AppVersion)[-dev] + # with `-dev` added if `useDevelopmentContainers` is specified + tag: v0.6.8-20210701_193232 + # pullPolicy is the pull policy + pullPolicy: "" + # useNetworkConnection specifies whether the discovery handler should make a networked connection + # with Agents, using its pod IP address when registering + useNetworkConnection: false + # port specifies (when useNetworkConnection is true) the port on which the discovery handler advertises its discovery service + port: 10000 + # nodeSelectors is the array of nodeSelectors used to target nodes for the discovery handler to run on + # This can be set from the helm command line using `--set coap.discovery.nodeSelectors.label="value"` + nodeSelectors: {} + resources: + # memoryRequest defines the minimum amount of RAM that must be available to this Pod + # for it to be scheduled by the Kubernetes Scheduler + memoryRequest: 11Mi + # cpuRequest defines the minimum amount of CPU that must be available to this Pod + # for it to be scheduled by the Kubernetes Scheduler + cpuRequest: 10m + # memoryLimit defines the maximum amount of RAM this Pod can consume. + memoryLimit: 24Mi + # cpuLimit defines the maximum amount of CPU this Pod can consume. + cpuLimit: 26m + onvif: configuration: # enabled defines whether to load a onvif configuration diff --git a/deployment/values.yaml b/deployment/values.yaml new file mode 100644 index 000000000..4210245b0 --- /dev/null +++ b/deployment/values.yaml @@ -0,0 +1,19 @@ +coap: + configuration: + enabled: true + discoveryDetails: + multicast: false + staticIpAddresses: + - 192.168.1.126 + brokerPod: + image: + # repository is the custom broker container reference + repository: gcr.io/kubernetes-e2e-test-images/dnsutils + # tag is the custom broker image tag + tag: "1.3" + brokerProperties: + test: okay + hello: kate + + discovery: + enabled: true From ddd5a8ebce0cdbf2074165bceccd3396ba7149f2 Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Tue, 13 Jul 2021 17:42:17 +0200 Subject: [PATCH 06/15] Remove deployment values --- deployment/values.yaml | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 deployment/values.yaml diff --git a/deployment/values.yaml b/deployment/values.yaml deleted file mode 100644 index 4210245b0..000000000 --- a/deployment/values.yaml +++ /dev/null @@ -1,19 +0,0 @@ -coap: - configuration: - enabled: true - discoveryDetails: - multicast: false - staticIpAddresses: - - 192.168.1.126 - brokerPod: - image: - # repository is the custom broker container reference - repository: gcr.io/kubernetes-e2e-test-images/dnsutils - # tag is the custom broker image tag - tag: "1.3" - brokerProperties: - test: okay - hello: kate - - discovery: - enabled: true From 4a1965406ff66f3d528fffd725de617dd0d61d9b Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Tue, 13 Jul 2021 18:12:36 +0200 Subject: [PATCH 07/15] Fix PR comments --- .../helm/templates/coap-configuration.yaml | 2 - .../templates/coap-discovery-handler.yaml | 3 - .../templates/debug-echo-configuration.yaml | 4 +- deployment/helm/values.yaml | 14 +- .../coap-discovery-handler/.gitignore | 5 - .../coap-discovery-handler/Cargo.lock | 3070 +++++++++++++++++ .../coap-discovery-handler/Cargo.toml | 1 - .../Dockerfile.discovery-handler | 20 - .../src/discovery_handler.rs | 45 +- .../src/discovery_utils.rs | 6 +- .../coap-discovery-handler/src/main.rs | 15 +- docs/proposals/coap.md | 4 - samples/brokers/coap-broker/src/http_coap.rs | 2 +- samples/brokers/coap-broker/src/main.rs | 21 +- 14 files changed, 3129 insertions(+), 83 deletions(-) delete mode 100644 discovery-handler-modules/coap-discovery-handler/.gitignore create mode 100644 discovery-handler-modules/coap-discovery-handler/Cargo.lock delete mode 100644 discovery-handler-modules/coap-discovery-handler/Dockerfile.discovery-handler diff --git a/deployment/helm/templates/coap-configuration.yaml b/deployment/helm/templates/coap-configuration.yaml index fa191e1e2..fca5f259d 100644 --- a/deployment/helm/templates/coap-configuration.yaml +++ b/deployment/helm/templates/coap-configuration.yaml @@ -34,8 +34,6 @@ spec: cpu: {{ .Values.coap.configuration.brokerPod.resources.cpuRequest }} limits: {{`"{{PLACEHOLDER}}"`}} : "1" - memory: {{ .Values.coap.configuration.brokerPod.resources.memoryLimit }} - cpu: {{ .Values.coap.configuration.brokerPod.resources.cpuLimit }} {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 6 }} diff --git a/deployment/helm/templates/coap-discovery-handler.yaml b/deployment/helm/templates/coap-discovery-handler.yaml index b98bf94f3..a4e9bae46 100644 --- a/deployment/helm/templates/coap-discovery-handler.yaml +++ b/deployment/helm/templates/coap-discovery-handler.yaml @@ -22,9 +22,6 @@ spec: requests: memory: {{ .Values.coap.discovery.resources.memoryRequest }} cpu: {{ .Values.coap.discovery.resources.cpuRequest }} - limits: - memory: {{ .Values.coap.discovery.resources.memoryLimit }} - cpu: {{ .Values.coap.discovery.resources.cpuLimit }} env: - name: DISCOVERY_HANDLERS_DIRECTORY value: /var/lib/akri diff --git a/deployment/helm/templates/debug-echo-configuration.yaml b/deployment/helm/templates/debug-echo-configuration.yaml index a85d59afb..36e3190b9 100644 --- a/deployment/helm/templates/debug-echo-configuration.yaml +++ b/deployment/helm/templates/debug-echo-configuration.yaml @@ -28,8 +28,6 @@ spec: cpu: {{ .Values.debugEcho.configuration.brokerPod.resources.cpuRequest }} limits: {{`"{{PLACEHOLDER}}"`}} : "1" - memory: {{ .Values.debugEcho.configuration.brokerPod.resources.memoryLimit }} - cpu: {{ .Values.debugEcho.configuration.brokerPod.resources.cpuLimit }} {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 6 }} @@ -64,4 +62,4 @@ spec: brokerProperties: {} {{- end }} capacity: 2 -{{- end }} \ No newline at end of file +{{- end }} diff --git a/deployment/helm/values.yaml b/deployment/helm/values.yaml index 2f6ea64a5..bc9d31a53 100644 --- a/deployment/helm/values.yaml +++ b/deployment/helm/values.yaml @@ -320,6 +320,8 @@ coap: # name is the Kubernetes resource name that will be created for this # coap configuration name: akri-coap + # discoveryHandlerName is the name of the Discovery Handler the Configuration is using + discoveryHandlerName: coap # brokerProperties is a map of properties that will be passed to any instances # created as a result of applying this coap configuration brokerProperties: {} @@ -336,9 +338,9 @@ coap: # container used by coap image: # repository is the coap broker container reference - repository: eu.gcr.io/fedra-301320/coap-core-broker + repository: # tag is the coap broker image tag - tag: v0.1.17-20210227_235612 + tag: latest # pullPolicy is the coap pull policy pullPolicy: "" resources: @@ -357,7 +359,7 @@ coap: createInstanceServices: true instanceService: # name is the description of the instance service - name: akri-coap-foo-instance-service + name: akri-coap-instance-service # type is the service type of the instance service type: ClusterIP # port is the service port of the instance service @@ -391,7 +393,7 @@ coap: # tag is the container tag # coap-configuration.yaml will default to v(AppVersion)[-dev] # with `-dev` added if `useDevelopmentContainers` is specified - tag: v0.6.8-20210701_193232 + tag: latest # pullPolicy is the pull policy pullPolicy: "" # useNetworkConnection specifies whether the discovery handler should make a networked connection @@ -409,10 +411,6 @@ coap: # cpuRequest defines the minimum amount of CPU that must be available to this Pod # for it to be scheduled by the Kubernetes Scheduler cpuRequest: 10m - # memoryLimit defines the maximum amount of RAM this Pod can consume. - memoryLimit: 24Mi - # cpuLimit defines the maximum amount of CPU this Pod can consume. - cpuLimit: 26m onvif: configuration: diff --git a/discovery-handler-modules/coap-discovery-handler/.gitignore b/discovery-handler-modules/coap-discovery-handler/.gitignore deleted file mode 100644 index 89c0bb339..000000000 --- a/discovery-handler-modules/coap-discovery-handler/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/target -**/*.rs.bk -Cargo.lock -bin/ -pkg/ \ No newline at end of file diff --git a/discovery-handler-modules/coap-discovery-handler/Cargo.lock b/discovery-handler-modules/coap-discovery-handler/Cargo.lock new file mode 100644 index 000000000..55fa0c501 --- /dev/null +++ b/discovery-handler-modules/coap-discovery-handler/Cargo.lock @@ -0,0 +1,3070 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + +[[package]] +name = "akri-discovery-utils" +version = "0.3.0" +source = "git+https://github.com/kate-goldenring/akri?branch=discovery-handlers-as-pods#a2b2b8cb37e3f838153154644378cc8f656a1211" +dependencies = [ + "akri-shared", + "anyhow", + "futures 0.3.13", + "log", + "prost", + "serde", + "serde_derive", + "serde_yaml", + "tokio 0.2.25", + "tonic", + "tonic-build", + "tower", +] + +[[package]] +name = "akri-shared" +version = "0.3.0" +source = "git+https://github.com/kate-goldenring/akri?branch=discovery-handlers-as-pods#a2b2b8cb37e3f838153154644378cc8f656a1211" +dependencies = [ + "anyhow", + "async-trait", + "either", + "env_logger", + "futures 0.1.31", + "futures 0.3.13", + "futures-util", + "k8s-openapi", + "kube", + "log", + "mockall", + "prometheus", + "rand 0.7.3", + "serde", + "serde_derive", + "serde_json", + "serde_yaml", + "tokio 0.2.25", + "tokio-core", + "tokio-signal", + "tonic", + "tower", + "warp", +] + +[[package]] +name = "anyhow" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "async-compression" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b72c1f1154e234325b50864a349b9c8e56939e266a4c307c0f159812df2f9537" +dependencies = [ + "bytes 0.5.6", + "flate2", + "futures-core", + "memchr", + "pin-project-lite 0.2.5", +] + +[[package]] +name = "async-stream" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22068c0c19514942eefcfd4daf8976ef1aad84e61539f95cd200c35202f80af5" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-trait" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "base64" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" +dependencies = [ + "byteorder", +] + +[[package]] +name = "base64" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" + +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "blake2b_simd" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "buf_redux" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" +dependencies = [ + "memchr", + "safemem", +] + +[[package]] +name = "bumpalo" +version = "3.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" + +[[package]] +name = "byteorder" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + +[[package]] +name = "bytes" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" + +[[package]] +name = "bytes" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" + +[[package]] +name = "cc" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "serde", + "time", + "winapi 0.3.9", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "core-foundation" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" + +[[package]] +name = "cpuid-bool" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" + +[[package]] +name = "crc32fast" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils 0.7.2", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +dependencies = [ + "autocfg", + "cfg-if 0.1.10", + "crossbeam-utils 0.7.2", + "lazy_static", + "maybe-uninit", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" +dependencies = [ + "cfg-if 0.1.10", + "crossbeam-utils 0.7.2", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg", + "cfg-if 0.1.10", + "lazy_static", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" +dependencies = [ + "autocfg", + "cfg-if 1.0.0", + "lazy_static", +] + +[[package]] +name = "difference" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "dirs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" +dependencies = [ + "cfg-if 0.1.10", + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" +dependencies = [ + "libc", + "redox_users", + "winapi 0.3.9", +] + +[[package]] +name = "downcast" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb454f0228b18c7f4c3b0ebbee346ed9c52e7443b0999cd543ff3571205701d" + +[[package]] +name = "dtoa" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e" + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "encoding_rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "env_logger" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "fixedbitset" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" + +[[package]] +name = "flate2" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" +dependencies = [ + "cfg-if 1.0.0", + "crc32fast", + "libc", + "miniz_oxide", +] + +[[package]] +name = "float-cmp" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding 2.1.0", +] + +[[package]] +name = "fragile" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69a039c3498dc930fe810151a34ba0c1c70b02b8625035592e74432f678591f2" + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + +[[package]] +name = "futures" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" + +[[package]] +name = "futures" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94" + +[[package]] +name = "futures-executor" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59" + +[[package]] +name = "futures-macro" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3" + +[[package]] +name = "futures-task" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80" + +[[package]] +name = "futures-timer" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" + +[[package]] +name = "futures-util" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite 0.2.5", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", +] + +[[package]] +name = "h2" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" +dependencies = [ + "bytes 0.5.6", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.3", + "indexmap", + "slab", + "tokio 0.2.25", + "tokio-util 0.3.1", + "tracing", + "tracing-futures", +] + +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" + +[[package]] +name = "headers" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0b7591fb62902706ae8e7aaff416b1b0fa2c0fd0878b46dc13baa3712d8a855" +dependencies = [ + "base64 0.13.0", + "bitflags", + "bytes 1.0.1", + "headers-core", + "http 0.2.3", + "mime", + "sha-1", + "time", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http 0.2.3", +] + +[[package]] +name = "heck" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "http" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" +dependencies = [ + "bytes 0.4.12", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" +dependencies = [ + "bytes 1.0.1", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" +dependencies = [ + "bytes 0.5.6", + "http 0.2.3", +] + +[[package]] +name = "httparse" +version = "1.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691" + +[[package]] +name = "httpdate" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "hyper" +version = "0.13.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a6f157065790a3ed2f88679250419b5cdd96e714a0d65f7797fd337186e96bb" +dependencies = [ + "bytes 0.5.6", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http 0.2.3", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project 1.0.5", + "socket2", + "tokio 0.2.25", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d979acc56dcb5b8dddba3917601745e877576475aa046df3226eabdecef78eed" +dependencies = [ + "bytes 0.5.6", + "hyper", + "native-tls", + "tokio 0.2.25", + "tokio-tls", +] + +[[package]] +name = "idna" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "input_buffer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a8a95243d5a0398cae618ec29477c6e3cb631152be5c19481f80bc71559754" +dependencies = [ + "bytes 0.5.6", +] + +[[package]] +name = "instant" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + +[[package]] +name = "ipnet" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" + +[[package]] +name = "itertools" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" + +[[package]] +name = "js-sys" +version = "0.3.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k8s-openapi" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8eb97e4ea14cef484aa56f44e93653cb6faa351b5f130d38584b3184b6ef5d1" +dependencies = [ + "base64 0.10.1", + "bytes 0.4.12", + "chrono", + "http 0.1.21", + "percent-encoding 2.1.0", + "serde", + "serde-value", + "serde_json", + "url", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "kube" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a8a53ca3e8cb9f6ebdf09cdd8943d08926da7ca8d5c1d89dee1ed0e8df0a2a" +dependencies = [ + "base64 0.11.0", + "chrono", + "dirs", + "either", + "futures 0.3.13", + "futures-timer", + "http 0.2.3", + "k8s-openapi", + "log", + "openssl", + "reqwest", + "serde", + "serde_derive", + "serde_json", + "serde_yaml", + "thiserror", + "time", + "url", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213" + +[[package]] +name = "linked-hash-map" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" + +[[package]] +name = "lock_api" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "lock_api" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" + +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] +name = "memoffset" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mime_guess" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow 0.2.2", + "net2", + "slab", + "winapi 0.2.8", +] + +[[package]] +name = "mio-named-pipes" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656" +dependencies = [ + "log", + "mio", + "miow 0.3.6", + "winapi 0.3.9", +] + +[[package]] +name = "mio-uds" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" +dependencies = [ + "iovec", + "libc", + "mio", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + +[[package]] +name = "miow" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" +dependencies = [ + "socket2", + "winapi 0.3.9", +] + +[[package]] +name = "mockall" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d614ad23f9bb59119b8b5670a85c7ba92c5e9adf4385c81ea00c51c8be33d5" +dependencies = [ + "cfg-if 1.0.0", + "downcast", + "fragile", + "lazy_static", + "mockall_derive", + "predicates", + "predicates-tree", +] + +[[package]] +name = "mockall_derive" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dd4234635bca06fc96c7368d038061e0aae1b00a764dc817e900dc974e3deea" +dependencies = [ + "cfg-if 1.0.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "multimap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1255076139a83bb467426e7f8d0134968a8118844faa755985e077cf31850333" + +[[package]] +name = "multipart" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050aeedc89243f5347c3e237e3e13dc76fbe4ae3742a57b94dc14f69acf76d4" +dependencies = [ + "buf_redux", + "httparse", + "log", + "mime", + "mime_guess", + "quick-error", + "rand 0.7.3", + "safemem", + "tempfile", + "twoway", +] + +[[package]] +name = "native-tls" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "net2" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "openssl" +version = "0.10.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038d43985d1ddca7a9900630d8cd031b56e4794eecc2e9ea39dd17aa04399a70" +dependencies = [ + "bitflags", + "cfg-if 1.0.0", + "foreign-types", + "lazy_static", + "libc", + "openssl-sys", +] + +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" + +[[package]] +name = "openssl-sys" +version = "0.9.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "ordered-float" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3305af35278dd29f46fcdd139e0b1fbfae2153f0e5928b39b035542dd31e37b7" +dependencies = [ + "num-traits", +] + +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +dependencies = [ + "lock_api 0.3.4", + "parking_lot_core 0.6.2", + "rustc_version", +] + +[[package]] +name = "parking_lot" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +dependencies = [ + "instant", + "lock_api 0.4.2", + "parking_lot_core 0.8.3", +] + +[[package]] +name = "parking_lot_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +dependencies = [ + "cfg-if 0.1.10", + "cloudabi", + "libc", + "redox_syscall 0.1.57", + "rustc_version", + "smallvec 0.6.14", + "winapi 0.3.9", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +dependencies = [ + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall 0.2.5", + "smallvec 1.6.1", + "winapi 0.3.9", +] + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "petgraph" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "pin-project" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15" +dependencies = [ + "pin-project-internal 0.4.27", +] + +[[package]] +name = "pin-project" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63" +dependencies = [ + "pin-project-internal 1.0.5", +] + +[[package]] +name = "pin-project-internal" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" + +[[package]] +name = "pin-project-lite" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cf491442e4b033ed1c722cb9f0df5fcfcf4de682466c46469c36bc47dc5548a" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] +name = "predicates" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeb433456c1a57cc93554dea3ce40b4c19c4057e41c55d4a0f3d84ea71c325aa" +dependencies = [ + "difference", + "float-cmp", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451" + +[[package]] +name = "predicates-tree" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f553275e5721409451eb85e15fd9a860a6e5ab4496eb215987502b5f5391f2" +dependencies = [ + "predicates-core", + "treeline", +] + +[[package]] +name = "prj" +version = "0.1.0" +dependencies = [ + "akri-discovery-utils", + "async-trait", + "tokio 0.2.25", + "tonic", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + +[[package]] +name = "proc-macro-nested" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" + +[[package]] +name = "proc-macro2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "procfs" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8809e0c18450a2db0f236d2a44ec0b4c1412d0eb936233579f0990faa5d5cd" +dependencies = [ + "bitflags", + "byteorder", + "flate2", + "hex", + "lazy_static", + "libc", +] + +[[package]] +name = "prometheus" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8425533e7122f0c3cc7a37e6244b16ad3a2cc32ae7ac6276e2a75da0d9c200d" +dependencies = [ + "cfg-if 1.0.0", + "fnv", + "lazy_static", + "libc", + "parking_lot 0.11.1", + "procfs", + "protobuf", + "regex", + "thiserror", +] + +[[package]] +name = "prost" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce49aefe0a6144a45de32927c77bd2859a5f7677b55f220ae5b744e87389c212" +dependencies = [ + "bytes 0.5.6", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b10678c913ecbd69350e8535c3aef91a8676c0773fc1d7b95cdd196d7f2f26" +dependencies = [ + "bytes 0.5.6", + "heck", + "itertools", + "log", + "multimap", + "petgraph", + "prost", + "prost-types", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537aa19b95acde10a12fec4301466386f757403de4cd4e5b4fa78fb5ecb18f72" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1834f67c0697c001304b75be76f67add9c89742eda3a085ad8ee0bb38c3417aa" +dependencies = [ + "bytes 0.5.6", + "prost", +] + +[[package]] +name = "protobuf" +version = "2.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f72884896d22e0da0e5b266cb9a780b791f6c3b2f5beab6368d6cd4f0dbb86" + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc 0.2.0", + "rand_pcg", +] + +[[package]] +name = "rand" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +dependencies = [ + "libc", + "rand_chacha 0.3.0", + "rand_core 0.6.2", + "rand_hc 0.3.0", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.2", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +dependencies = [ + "getrandom 0.2.2", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_hc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +dependencies = [ + "rand_core 0.6.2", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "redox_syscall" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" +dependencies = [ + "getrandom 0.1.16", + "redox_syscall 0.1.57", + "rust-argon2", +] + +[[package]] +name = "regex" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "reqwest" +version = "0.10.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0718f81a8e14c4dbb3b34cf23dc6aaf9ab8a0dfec160c534b3dbca1aaa21f47c" +dependencies = [ + "async-compression", + "base64 0.13.0", + "bytes 0.5.6", + "encoding_rs", + "futures-core", + "futures-util", + "http 0.2.3", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "lazy_static", + "log", + "mime", + "mime_guess", + "native-tls", + "percent-encoding 2.1.0", + "pin-project-lite 0.2.5", + "serde", + "serde_json", + "serde_urlencoded 0.7.0", + "tokio 0.2.25", + "tokio-tls", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi 0.3.9", +] + +[[package]] +name = "rust-argon2" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" +dependencies = [ + "base64 0.13.0", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils 0.8.3", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" +dependencies = [ + "base64 0.10.1", + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + +[[package]] +name = "schannel" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static", + "winapi 0.3.9", +] + +[[package]] +name = "scoped-tls" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" + +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "security-framework" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfd318104249865096c8da1dfabf09ddbb6d0330ea176812a62ec75e40c4166" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee48cdde5ed250b0d3252818f646e174ab414036edb884dde62d80a3ac6082d" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.123" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" + +[[package]] +name = "serde-value" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a65a7291a8a568adcae4c10a677ebcedbc6c9cec91c054dee2ce40b0e3290eb" +dependencies = [ + "ordered-float", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.123" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" +dependencies = [ + "dtoa", + "itoa", + "serde", + "url", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_yaml" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23" +dependencies = [ + "dtoa", + "linked-hash-map", + "serde", + "yaml-rust", +] + +[[package]] +name = "sha-1" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfebf75d25bd900fd1e7d11501efab59bc846dbc76196839663e6637bba9f25f" +dependencies = [ + "block-buffer", + "cfg-if 1.0.0", + "cpuid-bool", + "digest", + "opaque-debug", +] + +[[package]] +name = "signal-hook-registry" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" + +[[package]] +name = "smallvec" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" +dependencies = [ + "maybe-uninit", +] + +[[package]] +name = "smallvec" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" + +[[package]] +name = "socket2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "syn" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "tempfile" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "rand 0.8.3", + "redox_syscall 0.2.5", + "remove_dir_all", + "winapi 0.3.9", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +dependencies = [ + "once_cell", +] + +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi 0.3.9", +] + +[[package]] +name = "tinyvec" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "mio", + "num_cpus", + "tokio-codec", + "tokio-current-thread", + "tokio-executor", + "tokio-fs", + "tokio-io", + "tokio-reactor", + "tokio-sync", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", + "tokio-udp", + "tokio-uds", +] + +[[package]] +name = "tokio" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" +dependencies = [ + "bytes 0.5.6", + "fnv", + "futures-core", + "iovec", + "lazy_static", + "libc", + "memchr", + "mio", + "mio-named-pipes", + "mio-uds", + "num_cpus", + "pin-project-lite 0.1.12", + "signal-hook-registry", + "slab", + "tokio-macros", + "winapi 0.3.9", +] + +[[package]] +name = "tokio-codec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "tokio-io", +] + +[[package]] +name = "tokio-core" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87b1395334443abca552f63d4f61d0486f12377c2ba8b368e523f89e828cffd4" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "iovec", + "log", + "mio", + "scoped-tls 0.1.2", + "tokio 0.1.22", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-timer", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" +dependencies = [ + "futures 0.1.31", + "tokio-executor", +] + +[[package]] +name = "tokio-executor" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" +dependencies = [ + "crossbeam-utils 0.7.2", + "futures 0.1.31", +] + +[[package]] +name = "tokio-fs" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" +dependencies = [ + "futures 0.1.31", + "tokio-io", + "tokio-threadpool", +] + +[[package]] +name = "tokio-io" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "log", +] + +[[package]] +name = "tokio-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" +dependencies = [ + "crossbeam-utils 0.7.2", + "futures 0.1.31", + "lazy_static", + "log", + "mio", + "num_cpus", + "parking_lot 0.9.0", + "slab", + "tokio-executor", + "tokio-io", + "tokio-sync", +] + +[[package]] +name = "tokio-rustls" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3068d891551949b37681724d6b73666787cc63fa8e255c812a41d2513aff9775" +dependencies = [ + "futures-core", + "rustls", + "tokio 0.2.25", + "webpki", +] + +[[package]] +name = "tokio-signal" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0c34c6e548f101053321cba3da7cbb87a610b85555884c41b07da2eb91aff12" +dependencies = [ + "futures 0.1.31", + "libc", + "mio", + "mio-uds", + "signal-hook-registry", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "winapi 0.3.9", +] + +[[package]] +name = "tokio-sync" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" +dependencies = [ + "fnv", + "futures 0.1.31", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "iovec", + "mio", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-threadpool" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" +dependencies = [ + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils 0.7.2", + "futures 0.1.31", + "lazy_static", + "log", + "num_cpus", + "slab", + "tokio-executor", +] + +[[package]] +name = "tokio-timer" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" +dependencies = [ + "crossbeam-utils 0.7.2", + "futures 0.1.31", + "slab", + "tokio-executor", +] + +[[package]] +name = "tokio-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343" +dependencies = [ + "native-tls", + "tokio 0.2.25", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9e878ad426ca286e4dcae09cbd4e1973a7f8987d97570e2469703dd7f5720c" +dependencies = [ + "futures-util", + "log", + "pin-project 0.4.27", + "tokio 0.2.25", + "tungstenite", +] + +[[package]] +name = "tokio-udp" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "log", + "mio", + "tokio-codec", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-uds" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "iovec", + "libc", + "log", + "mio", + "mio-uds", + "tokio-codec", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-util" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" +dependencies = [ + "bytes 0.5.6", + "futures-core", + "futures-sink", + "log", + "pin-project-lite 0.1.12", + "tokio 0.2.25", +] + +[[package]] +name = "tokio-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" +dependencies = [ + "bytes 0.5.6", + "futures-core", + "futures-sink", + "log", + "pin-project-lite 0.1.12", + "tokio 0.2.25", +] + +[[package]] +name = "tonic" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08283643b1d483eb7f3fc77069e63b5cba3e4db93514b3d45470e67f123e4e48" +dependencies = [ + "async-stream", + "async-trait", + "base64 0.10.1", + "bytes 0.5.6", + "futures-core", + "futures-util", + "http 0.2.3", + "http-body", + "hyper", + "percent-encoding 1.0.1", + "pin-project 0.4.27", + "prost", + "prost-derive", + "tokio 0.2.25", + "tokio-rustls", + "tokio-util 0.2.0", + "tower", + "tower-balance", + "tower-load", + "tower-make", + "tower-service", + "tracing", + "tracing-futures", +] + +[[package]] +name = "tonic-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0436413ba71545bcc6c2b9a0f9d78d72deb0123c6a75ccdfe7c056f9930f5e52" +dependencies = [ + "proc-macro2", + "prost-build", + "quote", + "syn", +] + +[[package]] +name = "tower" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3169017c090b7a28fce80abaad0ab4f5566423677c9331bb320af7e49cfe62" +dependencies = [ + "futures-core", + "tower-buffer", + "tower-discover", + "tower-layer", + "tower-limit", + "tower-load-shed", + "tower-retry", + "tower-service", + "tower-timeout", + "tower-util", +] + +[[package]] +name = "tower-balance" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a792277613b7052448851efcf98a2c433e6f1d01460832dc60bef676bc275d4c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project 0.4.27", + "rand 0.7.3", + "slab", + "tokio 0.2.25", + "tower-discover", + "tower-layer", + "tower-load", + "tower-make", + "tower-ready-cache", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-buffer" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4887dc2a65d464c8b9b66e0e4d51c2fd6cf5b3373afc72805b0a60bce00446a" +dependencies = [ + "futures-core", + "pin-project 0.4.27", + "tokio 0.2.25", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-discover" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f6b5000c3c54d269cc695dff28136bb33d08cbf1df2c48129e143ab65bf3c2a" +dependencies = [ + "futures-core", + "pin-project 0.4.27", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" + +[[package]] +name = "tower-limit" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c3040c5dbed68abffaa0d4517ac1a454cd741044f33ab0eefab6b8d1361404" +dependencies = [ + "futures-core", + "pin-project 0.4.27", + "tokio 0.2.25", + "tower-layer", + "tower-load", + "tower-service", +] + +[[package]] +name = "tower-load" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cc79fc3afd07492b7966d7efa7c6c50f8ed58d768a6075dd7ae6591c5d2017b" +dependencies = [ + "futures-core", + "log", + "pin-project 0.4.27", + "tokio 0.2.25", + "tower-discover", + "tower-service", +] + +[[package]] +name = "tower-load-shed" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f021e23900173dc315feb4b6922510dae3e79c689b74c089112066c11f0ae4e" +dependencies = [ + "futures-core", + "pin-project 0.4.27", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-make" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce50370d644a0364bf4877ffd4f76404156a248d104e2cc234cd391ea5cdc965" +dependencies = [ + "tokio 0.2.25", + "tower-service", +] + +[[package]] +name = "tower-ready-cache" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eabb6620e5481267e2ec832c780b31cad0c15dcb14ed825df5076b26b591e1f" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "log", + "tokio 0.2.25", + "tower-service", +] + +[[package]] +name = "tower-retry" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6727956aaa2f8957d4d9232b308fe8e4e65d99db30f42b225646e86c9b6a952" +dependencies = [ + "futures-core", + "pin-project 0.4.27", + "tokio 0.2.25", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tower-timeout" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "127b8924b357be938823eaaec0608c482d40add25609481027b96198b2e4b31e" +dependencies = [ + "pin-project 0.4.27", + "tokio 0.2.25", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1093c19826d33807c72511e68f73b4a0469a3f22c2bd5f7d5212178b4b89674" +dependencies = [ + "futures-core", + "futures-util", + "pin-project 0.4.27", + "tower-service", +] + +[[package]] +name = "tracing" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" +dependencies = [ + "cfg-if 1.0.0", + "log", + "pin-project-lite 0.2.5", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a9bd1db7706f2373a190b0d067146caa39350c486f3d455b0e33b431f94c07" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project 1.0.5", + "tracing", +] + +[[package]] +name = "treeline" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "tungstenite" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0308d80d86700c5878b9ef6321f020f29b1bb9d5ff3cab25e75e23f3a492a23" +dependencies = [ + "base64 0.12.3", + "byteorder", + "bytes 0.5.6", + "http 0.2.3", + "httparse", + "input_buffer", + "log", + "rand 0.7.3", + "sha-1", + "url", + "utf-8", +] + +[[package]] +name = "twoway" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" +dependencies = [ + "memchr", +] + +[[package]] +name = "typenum" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +dependencies = [ + "matches", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding 2.1.0", +] + +[[package]] +name = "urlencoding" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9232eb53352b4442e40d7900465dfc534e8cb2dc8f18656fcb2ac16112b5593" + +[[package]] +name = "utf-8" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" + +[[package]] +name = "vcpkg" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" + +[[package]] +name = "version_check" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "warp" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f41be6df54c97904af01aa23e613d4521eed7ab23537cede692d4058f6449407" +dependencies = [ + "bytes 0.5.6", + "futures 0.3.13", + "headers", + "http 0.2.3", + "hyper", + "log", + "mime", + "mime_guess", + "multipart", + "pin-project 0.4.27", + "scoped-tls 1.0.0", + "serde", + "serde_json", + "serde_urlencoded 0.6.1", + "tokio 0.2.25", + "tokio-tungstenite", + "tower-service", + "tracing", + "tracing-futures", + "urlencoding", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasm-bindgen" +version = "0.2.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7" +dependencies = [ + "cfg-if 1.0.0", + "serde", + "serde_json", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e67a5806118af01f0d9045915676b22aaebecf4178ae7021bc171dab0b897ab" +dependencies = [ + "cfg-if 1.0.0", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1" + +[[package]] +name = "web-sys" +version = "0.3.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "which" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" +dependencies = [ + "libc", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winreg" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] diff --git a/discovery-handler-modules/coap-discovery-handler/Cargo.toml b/discovery-handler-modules/coap-discovery-handler/Cargo.toml index 7975d55a2..e2af38466 100644 --- a/discovery-handler-modules/coap-discovery-handler/Cargo.toml +++ b/discovery-handler-modules/coap-discovery-handler/Cargo.toml @@ -5,7 +5,6 @@ authors = ["Jiayi Hu "] edition = "2018" [dependencies] -# TODO: Change this to Akri main when the library is merged akri-discovery-utils = { path = "../../discovery-utils" } anyhow = "1.0.41" async-trait = "0.1.0" diff --git a/discovery-handler-modules/coap-discovery-handler/Dockerfile.discovery-handler b/discovery-handler-modules/coap-discovery-handler/Dockerfile.discovery-handler deleted file mode 100644 index dc7577ed7..000000000 --- a/discovery-handler-modules/coap-discovery-handler/Dockerfile.discovery-handler +++ /dev/null @@ -1,20 +0,0 @@ -FROM amd64/rust:1.47 as build -RUN rustup component add rustfmt --toolchain 1.47.0-x86_64-unknown-linux-gnu -RUN USER=root cargo new --bin dh -WORKDIR /dh -COPY ./Cargo.toml ./Cargo.toml -RUN cargo build --release && \ - rm ./src/*.rs && \ - DEP_PATH=`echo "./target/release/deps/coap-discovery-handler*" | tr - _` && \ - rm $DEP_PATH -COPY ./src ./src -RUN cargo build --release - -FROM amd64/debian:buster-slim -RUN apt-get update && \ - apt-get install -y --no-install-recommends libssl-dev && \ - apt-get clean -COPY --from=build /dh/target/release/coap-discovery-handler /coap-discovery-handler - -ENV RUST_LOG=coap_discovery_handler,akri_shared,akri_discovery_utils,akri_coap -ENTRYPOINT ["/coap-discovery-handler"] diff --git a/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs b/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs index 51300877a..a4c5e92e7 100644 --- a/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs +++ b/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs @@ -6,7 +6,7 @@ use akri_discovery_utils::discovery::{ }; use async_trait::async_trait; use coap_lite::CoapRequest; -use log::{error, info}; +use log::{debug, error, info}; use std::collections::HashMap; use std::time::Duration; use tokio::sync::mpsc; @@ -19,6 +19,9 @@ pub const DISCOVERY_INTERVAL_SECS: u64 = 10; pub const COAP_RESOURCE_TYPES_LABEL_ID: &str = "COAP_RESOURCE_TYPES"; pub const COAP_IP_LABEL_ID: &str = "COAP_IP"; +pub const COAP_PREFIX: &str = "coap://"; +pub const COAP_PORT: u16 = 5683; + /// This defines a query filter. The RFC7252 allows only one filter element. #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "camelCase")] @@ -55,6 +58,8 @@ impl DiscoveryHandler for DiscoveryHandlerImpl { &self, request: tonic::Request, ) -> Result, Status> { + info!("discover - coap discovery handler started"); + let mut register_sender = self.register_sender.clone(); let discover_request = request.get_ref(); let (mut discovered_devices_sender, discovered_devices_receiver) = @@ -63,7 +68,10 @@ impl DiscoveryHandler for DiscoveryHandlerImpl { deserialize_discovery_details(&discover_request.discovery_details) .map_err(|e| tonic::Status::new(tonic::Code::InvalidArgument, format!("{}", e)))?; - info!("Discovering config {:?}", discovery_handler_config); + debug!( + "discover - applying coap discovery config {:?}", + discovery_handler_config + ); let multicast = discovery_handler_config.multicast; let static_addrs = discovery_handler_config.static_ip_addresses; @@ -74,11 +82,11 @@ impl DiscoveryHandler for DiscoveryHandlerImpl { tokio::spawn(async move { loop { - let mut devices: Vec = vec![]; + let mut devices: Vec = Vec::new(); // Discover devices via static IPs - for ip_address in &static_addrs { - let coap_client = CoAPClientImpl::new((ip_address.as_str(), 5683)); + static_addrs.iter().for_each(|ip_address| { + let coap_client = CoAPClientImpl::new((ip_address.as_str(), COAP_PORT)); let device = discover_endpoint( &coap_client, &ip_address, @@ -89,14 +97,17 @@ impl DiscoveryHandler for DiscoveryHandlerImpl { match device { Ok(device) => devices.push(device), Err(e) => { - info!("Discovering endpoint {} went wrong: {}", ip_address, e); + info!( + "discover - discovering endpoint {} went wrong: {}", + ip_address, e + ); } } - } + }); // Discover devices via multicast if multicast { - let coap_client = CoAPClientImpl::new((multicast_addr.as_str(), 5683)); + let coap_client = CoAPClientImpl::new((multicast_addr.as_str(), COAP_PORT)); let discovered = discover_multicast(&coap_client, query_filter.as_ref(), timeout); @@ -126,6 +137,7 @@ impl DiscoveryHandler for DiscoveryHandlerImpl { } }); + info!("discover - coap discovery handler end"); Ok(Response::new(discovered_devices_receiver)) } } @@ -136,9 +148,15 @@ fn discover_endpoint( query_filter: Option<&QueryFilter>, timeout: Duration, ) -> Result { - let endpoint = format!("coap://{}:5683{}", ip_address, build_path(query_filter)); + let endpoint = format!( + "{}{}:{}{}", + COAP_PREFIX, + ip_address, + COAP_PORT, + build_path(query_filter) + ); - info!("Discovering resources on endpoint {}", endpoint); + info!("discover - discovering resources on endpoint {}", endpoint); let response = coap_client.get_with_timeout(endpoint.as_str(), timeout); @@ -146,7 +164,10 @@ fn discover_endpoint( Ok(response) => { let payload = String::from_utf8(response.message.payload) .expect("Received payload is not a string"); - info!("Device responded with {}", payload); + info!( + "discover - device {} responded to unicast request with {}", + ip_address, payload + ); let parsed = parse_payload(ip_address, query_filter, &payload); @@ -184,7 +205,7 @@ fn discover_multicast( let payload = String::from_utf8(response.message.payload).expect("Received payload is not a string"); info!( - "Device {} responded multicast with payload {}", + "discover - device {} responded to the multicast request with payload {}", ip_addr, payload ); diff --git a/discovery-handler-modules/coap-discovery-handler/src/discovery_utils.rs b/discovery-handler-modules/coap-discovery-handler/src/discovery_utils.rs index fd557c557..894b36b07 100644 --- a/discovery-handler-modules/coap-discovery-handler/src/discovery_utils.rs +++ b/discovery-handler-modules/coap-discovery-handler/src/discovery_utils.rs @@ -69,14 +69,14 @@ pub fn parse_link_value(link_value: &str) -> Vec<(String, String)> { let mut resources: Vec<(String, String)> = vec![]; while let Some(Ok((uri, mut attr_it))) = parser.next() { - debug!("Found CoAP resource {}", uri); + debug!("discovery_utils - found CoAP resource {}", uri); let mut resource = CoREResource::new(uri.to_string()); while let Some((attr, value)) = attr_it .next() .map(|(name, unquote)| (name, unquote.to_string())) { - debug!("attr {} value {}", attr, value); + debug!("discovery_utils - parsed attr {} value {}", attr, value); match attr { "rt" => resource.rtype = Some(value), @@ -100,7 +100,7 @@ pub fn parse_link_value(link_value: &str) -> Vec<(String, String)> { } } - info!("Parsed resources {:?}", resources); + info!("discovery_utils - parsed resources {:?}", resources); resources } diff --git a/discovery-handler-modules/coap-discovery-handler/src/main.rs b/discovery-handler-modules/coap-discovery-handler/src/main.rs index 5d1fd4658..675b91d64 100644 --- a/discovery-handler-modules/coap-discovery-handler/src/main.rs +++ b/discovery-handler-modules/coap-discovery-handler/src/main.rs @@ -11,21 +11,12 @@ use discovery_handler::DiscoveryHandlerImpl; async fn main() -> Result<(), Box> { env_logger::try_init()?; - // Specify the name of this DiscoveryHandler. A discovery handler is usually, but not necessarily, identified by - // the protocol it uses. let name = "coap"; - // Specify whether the devices discovered by this discovery handler are locally attached (or embedded) to nodes or are - // network based and usable/sharable by multiple nodes. - let shared = false; - // A DiscoveryHandler must handle the Agent dropping a connection due to a Configuration that utilizes this - // DiscoveryHandler being deleted or the Agent erroring. It is impossible to determine the cause of the - // disconnection, so in case the Agent did error out, the Discovery Handler should try to re-register. + let shared = true; let (register_sender, register_receiver) = tokio::sync::mpsc::channel(2); - // Create a DiscoveryHandler let discovery_handler = DiscoveryHandlerImpl::new(register_sender); - // This function will register the DiscoveryHandler with the Agent's registration socket - // and serve its discover service over UDS at the socket path - // `format!("{}/{}.sock"), env::var("DISCOVERY_HANDLERS_DIRECTORY"), name)`. + run_discovery_handler(discovery_handler, register_receiver, name, shared).await?; + Ok(()) } diff --git a/docs/proposals/coap.md b/docs/proposals/coap.md index 1707d442c..0e29bf206 100644 --- a/docs/proposals/coap.md +++ b/docs/proposals/coap.md @@ -59,10 +59,6 @@ The Akri Configuration defines a list of IP addresses to use for resource discov The current implementation would need a controller to accept queries about available resources and return the name of the Broker's service which can communicate to the device. The device is listed as a generic `akri.sh/coap-021dd7` resource on the node, which is too generic to be useful by any application. A better label would be `akri.sh/oic.r.temperature-021dd7`, the discovered resource. This would allow using the K8s controller for scheduling pods that need the resource. -- Is there any way to avoid coupling a CoAP device to any node? - -Akri deploys an agent to each cluster node and each agent has a running CoAP discovery handler. This behaviour results in a single CoAP device being discovered by multiple nodes and listed as multiple virtual CoAP devices. An immediate consequence is that the discovery handlers overflow the device with discovery requests, which causes the device to use more energy and maybe incur in concurrency issues, especially in the case of real-time devices. - ## Feature Requests - [x] Support multicast discovery in the discovery handler diff --git a/samples/brokers/coap-broker/src/http_coap.rs b/samples/brokers/coap-broker/src/http_coap.rs index ca57fee16..c2cd12c55 100644 --- a/samples/brokers/coap-broker/src/http_coap.rs +++ b/samples/brokers/coap-broker/src/http_coap.rs @@ -23,7 +23,7 @@ pub fn coap_to_http(packet: Packet) -> Response> { /// Converts a CoAP status code to HTTP status code. The CoAP status code field is described in /// RFC 7252 Section 3. /// -/// Put simply, a CoAP status code is 8bits, where the first 3 bits indicate the class and the +/// Put simply, a CoAP status code is 8 bits, where the first 3 bits indicate the class and the /// remaining 5 bits the type. For instance a status code 0x84 is 0b100_01000, which is 4_04 aka /// NotFound in HTTP :) fn coap_code_to_http_code(coap_code: MessageClass) -> u16 { diff --git a/samples/brokers/coap-broker/src/main.rs b/samples/brokers/coap-broker/src/main.rs index 70ebaeef4..e36e7fcdd 100644 --- a/samples/brokers/coap-broker/src/main.rs +++ b/samples/brokers/coap-broker/src/main.rs @@ -5,7 +5,7 @@ use coap::CoAPClient; use coap_lite::{ContentFormat, MessageClass, Packet, ResponseType}; use futures::{FutureExt, SinkExt, StreamExt}; use http_coap::coap_to_http; -use log::{debug, info}; +use log::{debug, error, info}; use std::collections::HashMap; use std::convert::Infallible; use std::sync::atomic::{AtomicU16, Ordering}; @@ -35,7 +35,7 @@ async fn handle_proxy(req: FullPath, state: Arc) -> Result) -> Result { - info!("Error while trying to request the device {}", e); + info!( + "handle_proxy - error while trying to send the request to the device {}", + e + ); let cache = state.cache.lock().unwrap(); let cached_packet = cache.get(&path.to_string()); @@ -100,7 +103,7 @@ async fn handle_stream( let ip_address = state.ip_address.clone(); let addr = format!("{}:5683", ip_address); let resource_uris = state.resource_uris.clone(); - info!("Streaming from {}", addr); + info!("handle_stream - streaming from {}", addr); let mut client = CoAPClient::new(addr) .map_err(|e| anyhow::anyhow!("Invalid client address while creating the client: {}", e))?; @@ -125,7 +128,7 @@ async fn handle_stream( tokio::task::spawn(coap_rx_stream.forward(ws_tx).map(|result| { if let Err(e) = result { - log::error!("websocket send error: {}", e); + error!("handle_stream - websocket send error: {}", e); } })); @@ -143,7 +146,7 @@ async fn handle_stream( } } Err(e) => { - log::error!("Websocket received an error: {}", e); + error!("handle_stream - websocket received an error: {}", e); break; } } @@ -172,7 +175,7 @@ async fn handle_stream( match coap_tx.send(Ok(message)) { Ok(()) => {} Err(e) => { - log::error!("Error sending the CoAP message: {}", e); + error!("handle_stream - error sending the CoAP message: {}", e); unobserve(observe_state.clone(), client_id); } } @@ -222,7 +225,7 @@ async fn main() { .collect(); info!( - "Found device IP {} with resource types {:?}", + "main - found device IP {} with resource types {:?}", device_ip, resource_types ); @@ -249,7 +252,7 @@ async fn main() { match handle_stream(path, state, websocket).await { Ok(()) => {} Err(e) => { - log::error!("Error handling the websocket stream: {}", e); + error!("main - error handling the websocket stream: {}", e); } } }) From 2bc91cf4bca32a897919354ba337ccbed33d9b88 Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Tue, 13 Jul 2021 23:27:23 +0200 Subject: [PATCH 08/15] Fix coap-broker integration --- .dockerignore | 3 +++ build/akri-containers.mk | 1 + build/containers/Dockerfile.coap-broker | 18 ++++++++++++++++++ deployment/helm/values.yaml | 8 ++++---- 4 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 build/containers/Dockerfile.coap-broker diff --git a/.dockerignore b/.dockerignore index 8b2bcbd4d..7d832cf5b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -45,6 +45,7 @@ !target/x86_64-unknown-linux-gnu/release/webhook-configuration !target/x86_64-unknown-linux-gnu/release/udev-discovery-handler !target/x86_64-unknown-linux-gnu/release/coap-discovery-handler +!target/x86_64-unknown-linux-gnu/release/coap-broker !target/x86_64-unknown-linux-gnu/release/debug-echo-discovery-handler !target/x86_64-unknown-linux-gnu/release/onvif-discovery-handler !target/x86_64-unknown-linux-gnu/release/opcua-discovery-handler @@ -60,6 +61,7 @@ !target/aarch64-unknown-linux-gnu/release/webhook-configuration !target/aarch64-unknown-linux-gnu/release/udev-discovery-handler !target/aarch64-unknown-linux-gnu/release/coap-discovery-handler +!target/aarch64-unknown-linux-gnu/release/coap-broker !target/aarch64-unknown-linux-gnu/release/debug-echo-discovery-handler !target/aarch64-unknown-linux-gnu/release/onvif-discovery-handler !target/aarch64-unknown-linux-gnu/release/opcua-discovery-handler @@ -75,6 +77,7 @@ !target/armv7-unknown-linux-gnueabihf/release/webhook-configuration !target/armv7-unknown-linux-gnueabihf/release/udev-discovery-handler !target/armv7-unknown-linux-gnueabihf/release/coap-discovery-handler +!target/armv7-unknown-linux-gnueabihf/release/coap-broker !target/armv7-unknown-linux-gnueabihf/release/debug-echo-discovery-handler !target/armv7-unknown-linux-gnueabihf/release/onvif-discovery-handler !target/armv7-unknown-linux-gnueabihf/release/opcua-discovery-handler diff --git a/build/akri-containers.mk b/build/akri-containers.mk index afc59c211..2b219695b 100644 --- a/build/akri-containers.mk +++ b/build/akri-containers.mk @@ -89,6 +89,7 @@ $(eval $(call add_rust_targets,agent-full,agent-full)) $(eval $(call add_rust_targets,udev,udev-video-broker)) $(eval $(call add_rust_targets,webhook-configuration,webhook-configuration)) $(eval $(call add_rust_targets,coap-discovery,coap-discovery)) +$(eval $(call add_rust_targets,coap-broker,coap-broker)) $(eval $(call add_rust_targets,debug-echo-discovery,debug-echo-discovery)) $(eval $(call add_rust_targets,onvif-discovery,onvif-discovery)) $(eval $(call add_rust_targets,opcua-discovery,opcua-discovery)) diff --git a/build/containers/Dockerfile.coap-broker b/build/containers/Dockerfile.coap-broker new file mode 100644 index 000000000..372e4724a --- /dev/null +++ b/build/containers/Dockerfile.coap-broker @@ -0,0 +1,18 @@ +ARG PLATFORM=amd64 +ARG CROSS_BUILD_TARGET=x86_64-unknown-linux-gnu +FROM ${PLATFORM}/debian:buster-slim +ARG CROSS_BUILD_TARGET +ARG BUILD_TYPE=release +RUN echo "Creating container based on ${PLATFORM}/debian:buster-slim" +RUN echo "Using Rust binaries from ${CROSS_BUILD_TARGET}/${BUILD_TYPE}" + +# Link the container to the Akri repository +LABEL org.opencontainers.image.source https://github.com/deislabs/akri + +# Copy over container legal notice +COPY ./build/container-images-legal-notice.md . + +RUN apt-get update && apt-get install -y --no-install-recommends libssl-dev openssl && apt-get clean +COPY ./target/${CROSS_BUILD_TARGET}/${BUILD_TYPE}/coap-broker /coap-broker +ENV RUST_LOG=coap_broker,api +CMD ["./coap-broker"] diff --git a/deployment/helm/values.yaml b/deployment/helm/values.yaml index bc9d31a53..a4e069e04 100644 --- a/deployment/helm/values.yaml +++ b/deployment/helm/values.yaml @@ -363,9 +363,9 @@ coap: # type is the service type of the instance service type: ClusterIP # port is the service port of the instance service - port: 6052 + port: 80 # targetPort is the service targetPort of the instance service - targetPort: 6052 + targetPort: 8083 # protocol is the service protocol of the instance service protocol: TCP # createConfigurationService is specified if a single service should automatically be @@ -377,9 +377,9 @@ coap: # type is the service type of the instance service type: ClusterIP # port is the service port of the instance service - port: 6052 + port: 80 # targetPort is the service targetPort of the instance service - targetPort: 6052 + targetPort: 8083 # protocol is the service protocol of the instance service protocol: TCP # discovery defines a set of values for a coap discovery handler DaemonSet From 8c9ebd27860386661d72235facac67c2b6951fba Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Wed, 14 Jul 2021 00:15:37 +0200 Subject: [PATCH 09/15] Add CoAP discovery handler integration tests --- Cargo.lock | 2 + .../coap-discovery-handler/Cargo.toml | 2 + .../src/discovery_handler.rs | 210 ++++++++++++++++++ 3 files changed, 214 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 76668e2a5..81b8dd3fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1031,6 +1031,7 @@ name = "coap-discovery-handler" version = "0.6.8" dependencies = [ "akri-discovery-utils", + "akri-shared", "anyhow", "async-trait", "coap", @@ -1041,6 +1042,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", + "serde_yaml", "tokio 0.2.25", "tonic", ] diff --git a/discovery-handler-modules/coap-discovery-handler/Cargo.toml b/discovery-handler-modules/coap-discovery-handler/Cargo.toml index e2af38466..f69b84126 100644 --- a/discovery-handler-modules/coap-discovery-handler/Cargo.toml +++ b/discovery-handler-modules/coap-discovery-handler/Cargo.toml @@ -15,8 +15,10 @@ log = "0.4.14" serde = "1.0.104" serde_json = "1.0.45" serde_derive = "1.0.104" +serde_yaml = "0.8.17" tokio = { version = "0.2", features = ["rt-threaded", "sync", "time", "stream", "fs", "macros", "uds"] } tonic = {version = "0.1.0", features = ["tls"] } [dev-dependencies] mockall = "0.9.0" +akri-shared = { path = "../../shared" } diff --git a/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs b/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs index a4c5e92e7..e051f1aa6 100644 --- a/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs +++ b/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs @@ -276,3 +276,213 @@ fn build_path(query_filter: Option<&QueryFilter>) -> String { String::from("/well-known/core") } } + +#[cfg(test)] +mod tests { + use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + + use super::super::discovery_utils::MockCoAPClient; + use super::*; + use akri_discovery_utils::discovery::v0::DiscoverRequest; + use akri_shared::akri::configuration::DiscoveryHandlerInfo; + use coap_lite::{CoapResponse, MessageType, Packet}; + use mockall::predicate::eq; + + fn create_core_response() -> CoapResponse { + let mut request = Packet::new(); + request.header.set_type(MessageType::Confirmable); + + let mut response = CoapResponse::new(&request).unwrap(); + + response.message.payload = br#";rt="oic.r.temperature";if="sensor", + ;rt="oic.r.light.brightness";if="sensor""# + .to_vec(); + + response + } + + fn configure_unicast_response(mock: &mut MockCoAPClient, timeout: Duration) { + mock.expect_get_with_timeout() + .withf(move |_url, tm| *tm == timeout) + .returning(|_url, _timeout| Ok(create_core_response())); + } + + #[tokio::test] + async fn test_basic_discover_ok() { + // Set node name for generating instance id + std::env::set_var("AGENT_NODE_NAME", "node-1"); + let mut mock_coap_client = MockCoAPClient::new(); + let timeout = Duration::from_secs(5); + configure_unicast_response(&mut mock_coap_client, timeout); + + let coap_yaml = r#" + name: coap + discoveryDetails: |+ + multicast: false + multicastIpAddress: 224.0.1.187 + staticIpAddresses: [] + discoveryTimeoutSeconds: 10 + "#; + let deserialized: DiscoveryHandlerInfo = serde_yaml::from_str(&coap_yaml).unwrap(); + let (register_sender, _register_receiver) = tokio::sync::mpsc::channel(2); + let discovery_handler = DiscoveryHandlerImpl::new(register_sender); + + let discover_request = tonic::Request::new(DiscoverRequest { + discovery_details: deserialized.discovery_details.clone(), + }); + let mut stream = discovery_handler + .discover(discover_request) + .await + .unwrap() + .into_inner(); + let devices = stream.recv().await.unwrap().unwrap().devices; + + assert_eq!(0, devices.len()); + } + + #[tokio::test] + async fn test_discover_resources_via_ip_addresses() { + // Set node name for generating instance id + std::env::set_var("AGENT_NODE_NAME", "node-1"); + let mut mock_coap_client = MockCoAPClient::new(); + let timeout = Duration::from_secs(5); + configure_unicast_response(&mut mock_coap_client, timeout); + + let ip_address = String::from("127.0.0.1"); + let query_filter = None; + let result = discover_endpoint( + &mock_coap_client, + &ip_address, + query_filter.as_ref(), + timeout, + ) + .unwrap(); + + assert_eq!( + result.properties.get(COAP_IP_LABEL_ID), + Some(&"127.0.0.1".to_string()) + ); + assert_eq!( + result.properties.get(COAP_RESOURCE_TYPES_LABEL_ID), + Some(&"oic.r.temperature,oic.r.light.brightness".to_string()) + ); + assert_eq!( + result.properties.get("oic.r.temperature"), + Some(&"/sensors/temp".to_string()) + ); + assert_eq!( + result.properties.get("oic.r.light.brightness"), + Some(&"/sensors/light".to_string()) + ); + } + + fn configure_multicast_scenario(mock: &mut MockCoAPClient, timeout: Duration) { + mock.expect_send_all_coap() + .times(1) + .returning(|_, _| Ok(())); + + mock.expect_set_receive_timeout() + .with(eq(Some(timeout))) + .returning(|_| Ok(())); + + let mut count = 0; + + // Receive response from 2 devices then time out + mock.expect_receive_from().times(3).returning(move || { + count += 1; + + let response = create_core_response(); + let src = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 5683); + + if count <= 2 { + Ok((response, src)) + } else { + Err(std::io::Error::new( + std::io::ErrorKind::TimedOut, + "Timed out", + )) + } + }); + } + + #[tokio::test] + async fn test_discover_resources_via_multicast() { + // Set node name for generating instance id + std::env::set_var("AGENT_NODE_NAME", "node-1"); + let mut mock_coap_client = MockCoAPClient::new(); + let timeout = Duration::from_secs(1); + configure_multicast_scenario(&mut mock_coap_client, timeout.clone()); + + let query_filter = None; + let results = + discover_multicast(&mock_coap_client, query_filter.as_ref(), timeout.clone()).unwrap(); + + assert_eq!(results.len(), 2); + } + + fn configure_query_filter_response(mock: &mut MockCoAPClient, query: &str) { + let pattern = format!("?{}", query); + + mock.expect_get_with_timeout() + .withf(move |url, _tm| url.ends_with(pattern.as_str())) + // It's okay for the response to be the same CoRE response, devices are not required to + // support filtering + .returning(|_url, _timeout| Ok(create_core_response())); + } + + #[tokio::test] + async fn test_query_filtering_href() { + // Set node name for generating instance id + std::env::set_var("AGENT_NODE_NAME", "node-1"); + let mut mock_coap_client = MockCoAPClient::new(); + let timeout = Duration::from_secs(5); + configure_query_filter_response(&mut mock_coap_client, "href=/sensors/temp"); + + let ip_address = String::from("127.0.0.1"); + let query_filter = Some(QueryFilter { + name: String::from("href"), + value: String::from("/sensors/temp"), + }); + let result = discover_endpoint( + &mock_coap_client, + &ip_address, + query_filter.as_ref(), + timeout, + ) + .unwrap(); + + assert_eq!( + result.properties.get("oic.r.temperature"), + Some(&"/sensors/temp".to_string()) + ); + assert_eq!(result.properties.get("oic.r.light.brightness"), None); + } + + #[tokio::test] + async fn test_query_filtering_resource_types() { + // Set node name for generating instance id + std::env::set_var("AGENT_NODE_NAME", "node-1"); + let mut mock_coap_client = MockCoAPClient::new(); + let timeout = Duration::from_secs(5); + configure_query_filter_response(&mut mock_coap_client, "rt=oic.r.temperature"); + + let ip_address = String::from("127.0.0.1"); + let query_filter = Some(QueryFilter { + name: String::from("rt"), + value: String::from("oic.r.temperature"), + }); + let result = discover_endpoint( + &mock_coap_client, + &ip_address, + query_filter.as_ref(), + timeout, + ) + .unwrap(); + + assert_eq!( + result.properties.get("oic.r.temperature"), + Some(&"/sensors/temp".to_string()) + ); + assert_eq!(result.properties.get("oic.r.light.brightness"), None); + } +} From 191bbfeddea98e970858e813b83db7bbd26471f2 Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Wed, 14 Jul 2021 23:24:29 +0200 Subject: [PATCH 10/15] Improve coap-broker error handling --- samples/brokers/coap-broker/src/http_coap.rs | 4 +- samples/brokers/coap-broker/src/main.rs | 51 +++++++++++--------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/samples/brokers/coap-broker/src/http_coap.rs b/samples/brokers/coap-broker/src/http_coap.rs index c2cd12c55..72b9048a0 100644 --- a/samples/brokers/coap-broker/src/http_coap.rs +++ b/samples/brokers/coap-broker/src/http_coap.rs @@ -31,9 +31,7 @@ fn coap_code_to_http_code(coap_code: MessageClass) -> u16 { let class = binary_code >> 5; let class_type = binary_code & 0b00011111; - let http_code = (class as u16) * 100 + (class_type as u16); - - http_code + (class as u16) * 100 + (class_type as u16) } fn content_format_to_content_type(content_format: ContentFormat) -> String { diff --git a/samples/brokers/coap-broker/src/main.rs b/samples/brokers/coap-broker/src/main.rs index e36e7fcdd..00400db32 100644 --- a/samples/brokers/coap-broker/src/main.rs +++ b/samples/brokers/coap-broker/src/main.rs @@ -57,10 +57,10 @@ async fn handle_proxy(req: FullPath, state: Arc) -> Result anyhow::Result<()> { env_logger::init(); let env_var_query = ActualEnvVarQuery {}; let device_ip = get_device_ip(&env_var_query); let resource_types = get_resources_types(&env_var_query); - let resource_uris: Vec = resource_types - .iter() - .map(|rtype| get_resource_uri(&env_var_query, rtype)) - .collect(); + let resource_uris: Vec = resource_types.and_then(|resource_types| { + info!( + "main - found device IP {} with resource types {:?}", + device_ip, resource_types + ); - info!( - "main - found device IP {} with resource types {:?}", - device_ip, resource_types - ); + let uris: anyhow::Result> = resource_types + .iter() + .map(|rtype| get_resource_uri(&env_var_query, rtype)) + .collect(); + + uris + })?; let state = Arc::new(AppState { ip_address: device_ip, @@ -261,6 +265,8 @@ async fn main() { let routes = health.or(stream).or(proxy).with(warp::log("api")); warp::serve(routes).run(([0, 0, 0, 0], 8083)).await; + + Ok(()) } fn with_state( @@ -277,23 +283,24 @@ fn get_device_ip(env_var_query: &impl EnvVarQuery) -> String { ip_address } -fn get_resources_types(env_var_query: &impl EnvVarQuery) -> Vec { - let types_string: String = env_var_query +fn get_resources_types(env_var_query: &impl EnvVarQuery) -> anyhow::Result> { + let types_string: anyhow::Result = env_var_query .get_env_var(COAP_RESOURCE_TYPES_LABEL_ID) - .expect("Device resource types not set in environment variable"); - let resource_types: Vec = types_string.split(",").map(|s| s.to_string()).collect(); + .map_err(|_e| anyhow::anyhow!("Device resource types not set in environment variable")); + let resource_types: anyhow::Result> = + types_string.map(|types_string| types_string.split(',').map(|s| s.to_string()).collect()); resource_types } -fn get_resource_uri(env_var_query: &impl EnvVarQuery, resource_type: &str) -> String { - let value = env_var_query.get_env_var(resource_type).expect( - format!( +fn get_resource_uri( + env_var_query: &impl EnvVarQuery, + resource_type: &str, +) -> anyhow::Result { + env_var_query.get_env_var(resource_type).map_err(|_e| { + anyhow::anyhow!( "Device resource URI for type {} not set in environment variable", resource_type ) - .as_str(), - ); - - value + }) } From c629440ab3c6fd529b064a21e46fb66f000a3bda Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Wed, 14 Jul 2021 23:28:05 +0200 Subject: [PATCH 11/15] Add coap-broker to version.sh --- version.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/version.sh b/version.sh index 2b33bee3e..fcbecbf7f 100755 --- a/version.sh +++ b/version.sh @@ -124,7 +124,7 @@ if [ "$CHECK" == "1" ]; then echo " Verified format: $BASEDIR/version.txt" fi - CARGO_FILES="$BASEDIR/shared/Cargo.toml $BASEDIR/agent/Cargo.toml $BASEDIR/controller/Cargo.toml $BASEDIR/samples/brokers/udev-video-broker/Cargo.toml $BASEDIR/webhooks/validating/configuration/Cargo.toml $BASEDIR/discovery-utils/Cargo.toml $BASEDIR/discovery-handlers/debug-echo/Cargo.toml $BASEDIR/discovery-handlers/onvif/Cargo.toml $BASEDIR/discovery-handlers/opcua/Cargo.toml $BASEDIR/discovery-handlers/udev/Cargo.toml $BASEDIR/discovery-handler-modules/coap-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/debug-echo-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/onvif-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/opcua-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/udev-discovery-handler/Cargo.toml" + CARGO_FILES="$BASEDIR/shared/Cargo.toml $BASEDIR/agent/Cargo.toml $BASEDIR/controller/Cargo.toml $BASEDIR/samples/brokers/udev-video-broker/Cargo.toml $BASEDIR/webhooks/validating/configuration/Cargo.toml $BASEDIR/discovery-utils/Cargo.toml $BASEDIR/discovery-handlers/debug-echo/Cargo.toml $BASEDIR/discovery-handlers/onvif/Cargo.toml $BASEDIR/discovery-handlers/opcua/Cargo.toml $BASEDIR/discovery-handlers/udev/Cargo.toml $BASEDIR/samples/brokers/coap-broker/Cargo.toml $BASEDIR/discovery-handler-modules/coap-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/debug-echo-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/onvif-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/opcua-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/udev-discovery-handler/Cargo.toml" TOML_VERSION_PATTERN="^version" TOML_VERSION="\"$(echo $VERSION)\"" for CARGO_FILE in $CARGO_FILES @@ -133,7 +133,7 @@ if [ "$CHECK" == "1" ]; then if [ "$?" -eq "1" ]; then exit 1; fi done - CARGO_LOCK_PROJECTS="controller akri-shared agent controller webhook-configuration udev-video-broker akri-discovery-utils akri-debug-echo akri-udev akri-onvif akri-opcua coap-discovery-handler debug-echo-discovery-handler onvif-discovery-handler udev-discovery-handler opcua-discovery-handler" + CARGO_LOCK_PROJECTS="controller akri-shared agent controller webhook-configuration udev-video-broker akri-discovery-utils akri-debug-echo akri-udev akri-onvif akri-opcua coap-broker coap-discovery-handler debug-echo-discovery-handler onvif-discovery-handler udev-discovery-handler opcua-discovery-handler" CARGO_LOCK_VERSION="\"$(echo $VERSION)\"" for CARGO_LOCK_PROJECT in $CARGO_LOCK_PROJECTS do @@ -187,7 +187,7 @@ then fi echo "Updating to version: $NEW_VERSION" - CARGO_FILES="$BASEDIR/shared/Cargo.toml $BASEDIR/agent/Cargo.toml $BASEDIR/controller/Cargo.toml $BASEDIR/samples/brokers/udev-video-broker/Cargo.toml $BASEDIR/webhooks/validating/configuration/Cargo.toml $BASEDIR/discovery-utils/Cargo.toml $BASEDIR/discovery-handlers/debug-echo/Cargo.toml $BASEDIR/discovery-handlers/onvif/Cargo.toml $BASEDIR/discovery-handlers/opcua/Cargo.toml $BASEDIR/discovery-handlers/udev/Cargo.toml $BASEDIR/discovery-handler-modules/coap-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/debug-echo-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/onvif-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/opcua-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/udev-discovery-handler/Cargo.toml" + CARGO_FILES="$BASEDIR/shared/Cargo.toml $BASEDIR/agent/Cargo.toml $BASEDIR/controller/Cargo.toml $BASEDIR/samples/brokers/udev-video-broker/Cargo.toml $BASEDIR/webhooks/validating/configuration/Cargo.toml $BASEDIR/discovery-utils/Cargo.toml $BASEDIR/discovery-handlers/debug-echo/Cargo.toml $BASEDIR/discovery-handlers/onvif/Cargo.toml $BASEDIR/discovery-handlers/opcua/Cargo.toml $BASEDIR/discovery-handlers/udev/Cargo.toml $BASEDIR/samples/brokers/coap-broker/Cargo.toml $BASEDIR/discovery-handler-modules/coap-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/debug-echo-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/onvif-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/opcua-discovery-handler/Cargo.toml $BASEDIR/discovery-handler-modules/udev-discovery-handler/Cargo.toml" TOML_VERSION_PATTERN="^version = .*" TOML_VERSION_LINE="version = \"$NEW_VERSION\"" for CARGO_FILE in $CARGO_FILES @@ -196,7 +196,7 @@ then if [ "$?" -eq "1" ]; then exit 1; fi done - CARGO_LOCK_PROJECTS="controller akri-shared agent controller webhook-configuration udev-video-broker akri-discovery-utils akri-debug-echo akri-udev akri-onvif akri-opcua coap-discovery-handler debug-echo-discovery-handler onvif-discovery-handler udev-discovery-handler opcua-discovery-handler" + CARGO_LOCK_PROJECTS="controller akri-shared agent controller webhook-configuration udev-video-broker akri-discovery-utils akri-debug-echo akri-udev akri-onvif akri-opcua coap-broker coap-discovery-handler debug-echo-discovery-handler onvif-discovery-handler udev-discovery-handler opcua-discovery-handler" CARGO_LOCK_VERSION_PATTERN="^version = .*" CARGO_LOCK_VERSION_LINE="version = \"$NEW_VERSION\"" for CARGO_LOCK_PROJECT in $CARGO_LOCK_PROJECTS From acd9c519be1308bea0e91810b6f7cc5a09bf014f Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Tue, 27 Jul 2021 00:00:56 +0200 Subject: [PATCH 12/15] Add CoAP configuration doc --- deployment/helm/values.yaml | 2 +- docs/coap-configuration.md | 83 +++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 docs/coap-configuration.md diff --git a/deployment/helm/values.yaml b/deployment/helm/values.yaml index 260f40a5d..4789bdba0 100644 --- a/deployment/helm/values.yaml +++ b/deployment/helm/values.yaml @@ -338,7 +338,7 @@ coap: # container used by coap image: # repository is the coap broker container reference - repository: + repository: ghcr.io/deislabs/akri/coap-broker # tag is the coap broker image tag tag: latest # pullPolicy is the coap pull policy diff --git a/docs/coap-configuration.md b/docs/coap-configuration.md new file mode 100644 index 000000000..d34307581 --- /dev/null +++ b/docs/coap-configuration.md @@ -0,0 +1,83 @@ +# Configuring Akri to Discover Devices via ONVIF + +The Constrained Application Protocol (CoAP) is a specialized web transfer protocol for use with constrained nodes and constrained (e.g., low-power, lossy) networks. More information about the protocol is available in [RFC7252](https://datatracker.ietf.org/doc/html/rfc7252). + +To try out CoAP, see the [CoAP end-to-end demo](coap-demo.md). + +All of Akri's components can be deployed by specifying values in its Helm chart during an installation. This section will cover the values that should be set to + +1. Deploy the CoAP Discovery Handlers +2. Apply a Configuration that tells Akri to discover CoAP devices using that Discovery Handler. + +## Deploying the CoAP Discovery Handler + +In order for the Agent to know how to discover CoAP servers an CoAP Discovery Handler must exist. Akri supports an Agent image that includes all supported Discovery Handlers. This Agent will be used if `agent.full=true`. + +By default, a slim Agent without any embedded Discovery Handlers is deployed and the required Discovery Handlers can be deployed as DaemonSets. This documentation will use the latter strategy, deploying distinct CoAP Discovery Handlers by specifying `coap.discovery.enabled=true` when installing Akri. + +## CoAP Configuration Settings + +Instead of having to assemble your own CoAP Configuration yaml, we have provided a [Helm +template](../deployment/helm/templates/coap-configuration.yaml). Helm allows us to parametrize the commonly modified fields in our configuration files, and we have provided many for CoAP (to see +them, run `helm inspect values akri-helm-charts/akri`). More information about the Akri Helm charts can be found in the [user guide](./user-guide.md#understanding-akri-helm-charts). + +To apply the CoAP Configuration to your cluster, simply set `coap.configuration.enabled=true` along with any of the following additional Configuration settings when installing Akri. + +### Discovery Handler Discovery Details Settings + +Discovery Handlers are passed discovery details that are set in a Configuration to determine what to discover, filter out of discovery, and so on. + +By default, the CoAP Discovery Handler doesn't require any additional information as it implements the multicast CoAP discovery (described in [Section 8 of RFC 7252](https://datatracker.ietf.org/doc/html/rfc7252#section-8)). The IPv4 address reserved for "All CoAP Nodes" is `224.0.1.187`. Devices must support the default port `5683` as specified by the standard. At the time of writing, IPv6 multicast is not supported in the CoAP Discovery Handler. + +Additional settings can be configured: + +| Helm Key | Type | Default | Description | +|---|---|---|---| +| coap.configuration.discoveryDetails.multicast | boolean | true | Enable IPv4 multicast discovery | +| coap.configuration.discoveryDetails.multicastIpAddress | string | 224.0.1.187 | The IPv4 to which the Discovery Handler sends the packets | +| coap.configuration.discoveryDetails.staticIpAddresses | Array of strings | [] | Additional static IP addresses to look for during the discovery. | +| coap.configuration.discoveryDetails.queryFilter | { name: string, value: string } | {} | Single name-value pair to filter the discovered resource, as described in [Section 4.1 of RFC 6690](https://datatracker.ietf.org/doc/html/rfc6690#section-4.1) | + +### Broker Pod Settings + +If you would like workloads ("broker" Pods) to be deployed automatically to discovered devices, a broker image should be specified in the Configuration. Alternatively, if it meets your scenario, you could use the Akri's default CoAP broker ("ghcr.io/deislabs/akri/coap-broker"). + +The default CoAP broker supports the following features: + +- Expose CoAP resources as REST resources via HTTP. **Only GET requests are currently supported** +- Cache CoAP responses for successful GET requests. If the device becomes unavailable, the cached resource is returned. + +If you would rather manually deploy pods to utilize the devices advertized by Akri, don't specify a broker pod and see our documentation on [requesting resources advertized by Akri](./requesting-akri-resources.md). + +| Helm Key | Value | Default | Description | +|---|---|---|---| +| coap.configuration.brokerPod.image.repository | image string | "" | image of broker Pod that should be deployed to discovered devices | +| coap.configuration.brokerPod.image.tag | tag string | "latest" | image tag of broker Pod that should be deployed to discovered devices | + +### Other settings + +The CoAP Discovery Handlers supports the same "Capacity" and "Automatic Service Creation" as OPC UA. Refer to the latter [documentation](https://github.com/deislabs/akri/blob/main/docs/opcua-configuration.md#disabling-automatic-service-creation) for additional information. + +### Installing Akri with the CoAP Configuration and Discovery Handler + +Leveraging the above settings, Akri can be installed with the CoAP Discovery Handler and an CoAP Configuration that specifies discovery via multicast: + +```bash +helm repo add akri-helm-charts https://deislabs.github.io/akri/ +helm install akri akri-helm-charts/akri \ + --set coap.discovery.enabled=true \ + --set coap.configuration.enabled=true +``` + +### Specifying additional IP addresses + +An operator can specify the addresses of one or more additional IP addresses to include in the discovery, like in the following example: + +```bash +helm repo add akri-helm-charts https://deislabs.github.io/akri/ +helm install akri akri-helm-charts/akri \ + --set coap.discovery.enabled=true \ + --set coap.configuration.enabled=true \ + --set coap.configuration.discoveryDetails.staticIpAddresses[0]="192.168.1.126" \ + --set coap.configuration.discoveryDetails.staticIpAddresses[1]="192.168.1.69" +``` From e87479beadeac0bf27bb9a25845bd2fa76ab87da Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Fri, 13 Aug 2021 15:59:23 +0200 Subject: [PATCH 13/15] Add CoAP demo --- Cargo.lock | 82 ++++++++++--- Cargo.toml | 1 + docs/coap-demo.md | 165 +++++++++++++++++++++++++++ samples/apps/coap-device/Cargo.toml | 11 ++ samples/apps/coap-device/src/main.rs | 58 ++++++++++ 5 files changed, 299 insertions(+), 18 deletions(-) create mode 100644 docs/coap-demo.md create mode 100644 samples/apps/coap-device/Cargo.toml create mode 100644 samples/apps/coap-device/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 3a3b84ef5..249e216ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,7 +22,7 @@ dependencies = [ "parking_lot 0.11.1", "pin-project-lite 0.2.6", "smallvec 1.6.1", - "tokio 1.6.1", + "tokio 1.10.0", "tokio-util 0.6.7", ] @@ -167,7 +167,7 @@ checksum = "bc7d7cd957c9ed92288a7c3c96af81fa5291f65247a76a34dac7b6af74e52ba0" dependencies = [ "actix-macros 0.2.0", "futures-core", - "tokio 1.6.1", + "tokio 1.10.0", ] [[package]] @@ -998,10 +998,10 @@ version = "0.9.2" source = "git+https://github.com/Covertness/coap-rs#aac20c39925511cb2fa9653a32c0cb02bfd0b1f0" dependencies = [ "bytes 0.5.6", - "coap-lite", + "coap-lite 0.4.1", "futures 0.3.15", "log", - "num-derive", + "num-derive 0.2.5", "num-traits", "regex", "serde", @@ -1010,22 +1010,51 @@ dependencies = [ "url 1.7.2", ] +[[package]] +name = "coap" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77d8f903accdde8a0d15a641b54874db940bad70284b2315f425f229ccb6f586" +dependencies = [ + "bytes 1.0.1", + "coap-lite 0.5.1", + "futures 0.3.15", + "log", + "num-derive 0.3.3", + "num-traits", + "regex", + "serde", + "tokio 1.10.0", + "tokio-stream", + "tokio-util 0.6.7", + "url 2.2.2", +] + [[package]] name = "coap-broker" version = "0.1.0" dependencies = [ "akri-shared", "anyhow", - "coap", - "coap-lite", + "coap 0.9.2", + "coap-lite 0.4.1", "env_logger", "futures 0.3.15", "log", - "tokio 1.6.1", + "tokio 1.10.0", "tokio-stream", "warp 0.3.1", ] +[[package]] +name = "coap-device" +version = "0.1.0" +dependencies = [ + "coap 0.11.1", + "coap-lite 0.5.1", + "tokio 1.10.0", +] + [[package]] name = "coap-discovery-handler" version = "0.6.8" @@ -1034,8 +1063,8 @@ dependencies = [ "akri-shared", "anyhow", "async-trait", - "coap", - "coap-lite", + "coap 0.9.2", + "coap-lite 0.4.1", "env_logger", "log", "mockall", @@ -1053,6 +1082,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d15e8642b7913b70e905e3d9bc1e01ff25ddcb650344d83e90ebbba9d2a4e03b" +[[package]] +name = "coap-lite" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7eafc0a93e6a6b76a58bc80278e497a182fcc9e62b8fbcccff702c5d76f5350" + [[package]] name = "concurrent-queue" version = "1.2.2" @@ -1690,7 +1725,7 @@ dependencies = [ "http 0.2.4", "indexmap", "slab", - "tokio 1.6.1", + "tokio 1.10.0", "tokio-util 0.6.7", "tracing", ] @@ -1870,7 +1905,7 @@ dependencies = [ "itoa", "pin-project 1.0.7", "socket2 0.4.0", - "tokio 1.6.1", + "tokio 1.10.0", "tower-service", "tracing", "want", @@ -2400,6 +2435,17 @@ dependencies = [ "syn 0.15.44", ] +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.72", +] + [[package]] name = "num-integer" version = "0.1.44" @@ -3235,7 +3281,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded 0.7.0", - "tokio 1.6.1", + "tokio 1.10.0", "url 2.2.2", "wasm-bindgen", "wasm-bindgen-futures", @@ -3853,9 +3899,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.6.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a38d31d7831c6ed7aad00aa4c12d9375fd225a6dd77da1d25b707346319a975" +checksum = "01cf844b23c6131f624accf65ce0e4e9956a8bb329400ea5bcc26ae3a5c20b0b" dependencies = [ "autocfg", "bytes 1.0.1", @@ -4031,7 +4077,7 @@ checksum = "f8864d706fdb3cc0843a49647ac892720dac98a6eeb818b77190592cf4994066" dependencies = [ "futures-core", "pin-project-lite 0.2.6", - "tokio 1.6.1", + "tokio 1.10.0", ] [[package]] @@ -4119,7 +4165,7 @@ dependencies = [ "futures-util", "log", "pin-project 1.0.7", - "tokio 1.6.1", + "tokio 1.10.0", "tungstenite 0.12.0", ] @@ -4195,7 +4241,7 @@ dependencies = [ "futures-sink", "log", "pin-project-lite 0.2.6", - "tokio 1.6.1", + "tokio 1.10.0", ] [[package]] @@ -4810,7 +4856,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded 0.7.0", - "tokio 1.6.1", + "tokio 1.10.0", "tokio-stream", "tokio-tungstenite 0.13.0", "tokio-util 0.6.7", diff --git a/Cargo.toml b/Cargo.toml index 69d55aff8..9329ea7b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "shared", "agent", "controller", + "samples/apps/coap-device", "samples/brokers/coap-broker", "samples/brokers/udev-video-broker", "webhooks/validating/configuration", diff --git a/docs/coap-demo.md b/docs/coap-demo.md new file mode 100644 index 000000000..b7180e2b6 --- /dev/null +++ b/docs/coap-demo.md @@ -0,0 +1,165 @@ +# CoAP demo + +The Constrained Application Protocol (CoAP) is a specialized web transfer protocol for use with constrained nodes and constrained (e.g., low-power, lossy) networks. This demo will show how Akri can discover CoAP devices and allow cluster applications to communicate with them. To do so, the built-in Akri CoAP Broker exposes CoAP resources as REST resources via HTTP. + +The demo consists of the following steps: + +1. Initialize a CoAP device with two resources: temperature and light brightness. +2. Start an Akri installation +3. Deploy a Kubernetes application which requests the temperature via HTTP + +## Creating CoAP devices + +If you don't have existing devices running CoAP, you can create a CoAP server by yourself on the running machine. + +We will use Rust and [coap-rs](https://github.com/Covertness/coap-rs) in this section, but any language implementation of CoAP is fine (e.g. [node-coap](https://github.com/mcollina/node-coap)). The final example can be found in `/samples/app/coap-device`. + +1. Create a new Rust project anywhere you like + + ``` + cargo new coap-device + ``` + +2. Add the following dependencies to `Cargo.toml` + + ```toml + [dependencies] + coap = "0.11.0" + coap-lite = "0.5" + tokio = "1.8.1" + ``` + +3. Implement a simple CoAP server in `src/main.rs`, which exposes the `/sensors/temp` and `/sensors/light` resources. + + ```rs + #![feature(async_closure)] + + use coap::Server; + use coap_lite::{ContentFormat, RequestType as Method, ResponseType as Status}; + use tokio::runtime::Runtime; + + fn main() { + let addr = "0.0.0.0:5683"; + + Runtime::new().unwrap().block_on(async move { + let mut server = Server::new(addr).unwrap(); + println!("CoAP server on {}", addr); + + server + .run(async move |request| { + let method = request.get_method().clone(); + let path = request.get_path(); + let mut response = request.response?; + + match (method, path.as_str()) { + (Method::Get, "well-known/core") => { + response + .message + .set_content_format(ContentFormat::ApplicationLinkFormat); + response.message.payload = + br#";rt="oic.r.temperature";if="sensor", + ;rt="oic.r.light.brightness";if="sensor""# + .to_vec(); + } + (Method::Get, "sensors/temp") => { + response + .message + .set_content_format(ContentFormat::TextPlain); + response.message.payload = b"42".to_vec(); + } + (Method::Get, "sensors/light") => { + response + .message + .set_content_format(ContentFormat::TextPlain); + response.message.payload = b"100".to_vec(); + } + _ => { + response.set_status(Status::NotFound); + response.message.payload = b"Not found".to_vec(); + } + } + + Some(response) + }) + .await + .unwrap(); + }); + } + ``` + +4. Run the server + + ``` + cargo run + ``` + +It's not necessary, but you can check if the server is correctly up-and-running creating a separate Rust project for a CoAP client with the following `main.rs`: + +```rs +use coap::CoAPClient; + +fn main() { + let url = "coap://192.168.1.126:5683/sensors/temp"; // Properly set your machine's IP + let response = CoAPClient::get(url).unwrap(); + println!("Server reply: {}", String::from_utf8(response.message.payload).unwrap()); +} +``` + +## Running Akri + +Now it is time to install the Akri using Helm. When installing Akri, we can specify that we want to deploy the CoAP Discovery Handlers by setting the helm value `coap.discovery.enabled=true`. We also specify that we want to create a CoAP Configuration with `--set coap.configuration.enabled=true`. + +In the Configuration, we need to specify our CoAP server's static IP address since otherwise the the Discovery Handler's default behaviour is to use the broadcast method: `--set coap.configuration.discoveryDetails.staticIpAddresses[0] = "192.168.1.126"`. + +The final CLI commands should look like this: + + ```sh +helm repo add akri-helm-charts https://deislabs.github.io/akri/ +helm install akri akri-helm-charts/akri \ + --set coap.discovery.enabled=true \ + --set coap.configuration.enabled=true \ + --set coap.configuration.discoveryDetails.staticIpAddresses[0] = "192.168.1.126" +``` + +The Akri Discovery Handler will discover the CoAP server and create an instance. + + +```sh +kubectl get pods +``` + +The result should look like this: + +``` +NAME READY STATUS RESTARTS AGE +akri-agent-daemonset-p8w8z 1/1 Running 0 75s +akri-coap-discovery-daemonset-sq6pt 1/1 Running 0 75s +akri-controller-deployment-5bc76f77d8-9ldws 1/1 Running 0 75s +kind-control-plane-akri-coap-920f97-pod 1/1 Running 0 64s +``` + +To inspect more of the elements of Akri: + +- Run `kubectl get crd`, and you should see the CRDs listed. +- Run `kubectl get akric`, and you should see `akri-coap`. +- The instances can be seen by running `kubectl get akrii` and + further inspected by running `kubectl get akrii akri-coap- -o yaml` + +## Deploy a Kubernetes application which requests the temperature via HTTP + +The Akri CoAP built-in Broker Pod is automatically deployed when an instance is created. The Broker exposes a RESTful endpoint which translates HTTP request to CoAP requests. To inspect the associated Kubernetes Service, run `kubectl get crd`. + +``` +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +akri-coap-920f97-svc ClusterIP 10.96.190.197 80/TCP 10m +akri-coap-svc ClusterIP 10.96.87.25 80/TCP 10m +``` + +We can now deploy a simple application which just allows to send normal HTTP requests using the terminal. + +``` +kubectl run curl --image=radial/busyboxplus:curl -i --tty + +[ root@curl:/ ]$ curl http://akri-coap-920f97-svc/sensors/temp +``` + diff --git a/samples/apps/coap-device/Cargo.toml b/samples/apps/coap-device/Cargo.toml new file mode 100644 index 000000000..5cf04236b --- /dev/null +++ b/samples/apps/coap-device/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "coap-device" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +coap = "0.11.0" +coap-lite = "0.5" +tokio = "1.8.1" diff --git a/samples/apps/coap-device/src/main.rs b/samples/apps/coap-device/src/main.rs new file mode 100644 index 000000000..0c73a6a35 --- /dev/null +++ b/samples/apps/coap-device/src/main.rs @@ -0,0 +1,58 @@ +#![feature(async_closure)] + +use coap::Server; +use coap_lite::{ContentFormat, RequestType as Method, ResponseType as Status}; +use tokio::runtime::Runtime; + +fn main() { + let addr = "0.0.0.0:5683"; + + Runtime::new().unwrap().block_on(async move { + let mut server = Server::new(addr).unwrap(); + println!("CoAP server on {}", addr); + + server + .run(async move |request| { + println!( + "Received request from {} for resource {}", + request.source.unwrap(), + request.get_path() + ); + let method = request.get_method().clone(); + let path = request.get_path(); + let mut response = request.response?; + + match (method, path.as_str()) { + (Method::Get, "well-known/core") => { + response + .message + .set_content_format(ContentFormat::ApplicationLinkFormat); + response.message.payload = + br#";rt="oic.r.temperature";if="sensor", + ;rt="oic.r.light.brightness";if="sensor""# + .to_vec(); + } + (Method::Get, "sensors/temp") => { + response + .message + .set_content_format(ContentFormat::TextPlain); + response.message.payload = b"42".to_vec(); + } + (Method::Get, "sensors/light") => { + response + .message + .set_content_format(ContentFormat::TextPlain); + response.message.payload = b"100".to_vec(); + } + _ => { + response.set_status(Status::NotFound); + response.message.payload = b"Not found".to_vec(); + } + } + + Some(response) + }) + .await + .unwrap(); + }); +} From 647f47525e5250aaa65b3b12de7b5019a97f64d0 Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Fri, 13 Aug 2021 23:36:05 +0200 Subject: [PATCH 14/15] Parallelize discovery for static addresses --- Cargo.lock | 17 ++--- .../coap-discovery-handler/Cargo.toml | 5 +- .../src/discovery_handler.rs | 62 ++++++++++++------- samples/brokers/coap-broker/Cargo.toml | 2 +- 4 files changed, 49 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dfc58368e..be249b7d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -998,7 +998,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77d8f903accdde8a0d15a641b54874db940bad70284b2315f425f229ccb6f586" dependencies = [ "bytes 1.0.1", - "coap-lite 0.5.1", + "coap-lite", "futures 0.3.16", "log", "num-derive", @@ -1017,7 +1017,7 @@ version = "0.11.1" source = "git+https://github.com/Covertness/coap-rs#02012abe3aa00fc2c96aaacff91449d71fd8980f" dependencies = [ "bytes 1.0.1", - "coap-lite 0.5.1", + "coap-lite", "futures 0.3.16", "log", "num-derive", @@ -1037,7 +1037,7 @@ dependencies = [ "akri-shared", "anyhow", "coap 0.11.1 (git+https://github.com/Covertness/coap-rs)", - "coap-lite 0.4.1", + "coap-lite", "env_logger", "futures 0.3.16", "log", @@ -1051,7 +1051,7 @@ name = "coap-device" version = "0.1.0" dependencies = [ "coap 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "coap-lite 0.5.1", + "coap-lite", "tokio 1.9.0", ] @@ -1064,8 +1064,9 @@ dependencies = [ "anyhow", "async-trait", "coap 0.11.1 (git+https://github.com/Covertness/coap-rs)", - "coap-lite 0.4.1", + "coap-lite", "env_logger", + "futures 0.3.16", "log", "mockall", "serde", @@ -1076,12 +1077,6 @@ dependencies = [ "tonic", ] -[[package]] -name = "coap-lite" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15e8642b7913b70e905e3d9bc1e01ff25ddcb650344d83e90ebbba9d2a4e03b" - [[package]] name = "coap-lite" version = "0.5.1" diff --git a/discovery-handler-modules/coap-discovery-handler/Cargo.toml b/discovery-handler-modules/coap-discovery-handler/Cargo.toml index f69b84126..a4e71274f 100644 --- a/discovery-handler-modules/coap-discovery-handler/Cargo.toml +++ b/discovery-handler-modules/coap-discovery-handler/Cargo.toml @@ -7,9 +7,9 @@ edition = "2018" [dependencies] akri-discovery-utils = { path = "../../discovery-utils" } anyhow = "1.0.41" -async-trait = "0.1.0" +async-trait = "0.1.51" coap = { git = "https://github.com/Covertness/coap-rs" } -coap-lite = "0.4.1" +coap-lite = "0.5" env_logger = "0.8.4" log = "0.4.14" serde = "1.0.104" @@ -18,6 +18,7 @@ serde_derive = "1.0.104" serde_yaml = "0.8.17" tokio = { version = "0.2", features = ["rt-threaded", "sync", "time", "stream", "fs", "macros", "uds"] } tonic = {version = "0.1.0", features = ["tls"] } +futures = "0.3.16" [dev-dependencies] mockall = "0.9.0" diff --git a/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs b/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs index e051f1aa6..a877b2de0 100644 --- a/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs +++ b/discovery-handler-modules/coap-discovery-handler/src/discovery_handler.rs @@ -6,11 +6,12 @@ use akri_discovery_utils::discovery::{ }; use async_trait::async_trait; use coap_lite::CoapRequest; +use futures::future::join_all; use log::{debug, error, info}; -use std::collections::HashMap; -use std::time::Duration; -use tokio::sync::mpsc; +use std::{collections::HashMap, sync::Arc}; +use std::{sync::Mutex, time::Duration}; use tokio::time::delay_for; +use tokio::{sync::mpsc, task::JoinHandle}; use tonic::{Response, Status}; // TODO: make this configurable @@ -82,28 +83,40 @@ impl DiscoveryHandler for DiscoveryHandlerImpl { tokio::spawn(async move { loop { - let mut devices: Vec = Vec::new(); + let shared_devices: Arc>> = Arc::new(Mutex::new(Vec::new())); // Discover devices via static IPs - static_addrs.iter().for_each(|ip_address| { - let coap_client = CoAPClientImpl::new((ip_address.as_str(), COAP_PORT)); - let device = discover_endpoint( - &coap_client, - &ip_address, - query_filter.as_ref(), - timeout, - ); - - match device { - Ok(device) => devices.push(device), - Err(e) => { - info!( - "discover - discovering endpoint {} went wrong: {}", - ip_address, e + let requests: Vec> = static_addrs + .clone() + .into_iter() + .map(|ip_address| { + let shared_devices = shared_devices.clone(); + let query_filter = query_filter.clone(); + + tokio::task::spawn_blocking(move || { + let mut shared_devices = shared_devices.lock().unwrap(); + let coap_client = CoAPClientImpl::new((ip_address.as_str(), COAP_PORT)); + let device = discover_endpoint( + &coap_client, + &ip_address, + query_filter.as_ref(), + timeout, ); - } - } - }); + + match device { + Ok(device) => shared_devices.push(device), + Err(e) => { + info!( + "discover - discovering endpoint {} went wrong: {}", + ip_address, e + ); + } + } + }) + }) + .collect(); + + join_all(requests).await; // Discover devices via multicast if multicast { @@ -113,7 +126,7 @@ impl DiscoveryHandler for DiscoveryHandlerImpl { match discovered { Ok(mut discovered) => { - devices.append(&mut discovered); + shared_devices.lock().unwrap().append(&mut discovered); } Err(e) => { error!("Error while discovering devices via multicast {}", e); @@ -121,6 +134,9 @@ impl DiscoveryHandler for DiscoveryHandlerImpl { } } + let lock = Arc::try_unwrap(shared_devices).expect("Lock still has multiple owners"); + let devices = lock.into_inner().expect("Mutex cannot be locked"); + if let Err(e) = discovered_devices_sender .send(Ok(DiscoverResponse { devices })) .await diff --git a/samples/brokers/coap-broker/Cargo.toml b/samples/brokers/coap-broker/Cargo.toml index 066cbb757..45547a153 100644 --- a/samples/brokers/coap-broker/Cargo.toml +++ b/samples/brokers/coap-broker/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" [dependencies] akri-shared = { path = "../../../shared" } coap = { git = "https://github.com/Covertness/coap-rs" } -coap-lite = "0.4" +coap-lite = "0.5" env_logger = "0.8.4" log = "0.4.14" tokio = { version = "1", features = ["full"] } From 6191cdf35cbe967eddeacf4c860e43f34b4b0031 Mon Sep 17 00:00:00 2001 From: Jiayi Hu Date: Sat, 14 Aug 2021 00:44:28 +0200 Subject: [PATCH 15/15] Fix typos --- docs/coap-configuration.md | 2 +- docs/coap-demo.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/coap-configuration.md b/docs/coap-configuration.md index d34307581..d2992e2e7 100644 --- a/docs/coap-configuration.md +++ b/docs/coap-configuration.md @@ -1,4 +1,4 @@ -# Configuring Akri to Discover Devices via ONVIF +# Configuring Akri to Discover Devices via CoAP The Constrained Application Protocol (CoAP) is a specialized web transfer protocol for use with constrained nodes and constrained (e.g., low-power, lossy) networks. More information about the protocol is available in [RFC7252](https://datatracker.ietf.org/doc/html/rfc7252). diff --git a/docs/coap-demo.md b/docs/coap-demo.md index b7180e2b6..f8da6af50 100644 --- a/docs/coap-demo.md +++ b/docs/coap-demo.md @@ -1,12 +1,12 @@ # CoAP demo -The Constrained Application Protocol (CoAP) is a specialized web transfer protocol for use with constrained nodes and constrained (e.g., low-power, lossy) networks. This demo will show how Akri can discover CoAP devices and allow cluster applications to communicate with them. To do so, the built-in Akri CoAP Broker exposes CoAP resources as REST resources via HTTP. +The Constrained Application Protocol (CoAP) is a specialized web transfer protocol with constrained nodes and constrained (e.g., low-power, lossy) networks. This demo will show how Akri can discover CoAP devices and allow cluster applications to communicate with them. To do so, the built-in Akri CoAP Broker exposes CoAP resources as REST resources via HTTP. The demo consists of the following steps: 1. Initialize a CoAP device with two resources: temperature and light brightness. 2. Start an Akri installation -3. Deploy a Kubernetes application which requests the temperature via HTTP +3. Deploy a Kubernetes application that requests the temperature via HTTP ## Creating CoAP devices @@ -93,7 +93,7 @@ We will use Rust and [coap-rs](https://github.com/Covertness/coap-rs) in this se cargo run ``` -It's not necessary, but you can check if the server is correctly up-and-running creating a separate Rust project for a CoAP client with the following `main.rs`: +It's not necessary, but you can check if the server is correctly up and running creating a separate Rust project for a CoAP client with the following `main.rs`: ```rs use coap::CoAPClient; @@ -109,7 +109,7 @@ fn main() { Now it is time to install the Akri using Helm. When installing Akri, we can specify that we want to deploy the CoAP Discovery Handlers by setting the helm value `coap.discovery.enabled=true`. We also specify that we want to create a CoAP Configuration with `--set coap.configuration.enabled=true`. -In the Configuration, we need to specify our CoAP server's static IP address since otherwise the the Discovery Handler's default behaviour is to use the broadcast method: `--set coap.configuration.discoveryDetails.staticIpAddresses[0] = "192.168.1.126"`. +In the Configuration, we need to specify our CoAP server's static IP address. Otherwise, the Discovery Handler's default behaviour is to use the broadcast method: `--set coap.configuration.discoveryDetails.staticIpAddresses[0] = "192.168.1.126"`. The final CLI commands should look like this: