From 0a43883dd2389822b8ca0b5d7f93b132222572e6 Mon Sep 17 00:00:00 2001 From: Paul Butler Date: Tue, 3 Dec 2024 12:11:53 +0000 Subject: [PATCH] Refactor parts of Plane into a `plane-common` crate (DIS-2967) (#849) The main `plane` crate contains a client, but depending on it in another project requires bringing in _all_ of Plane, including the openssl dependency. This breaks the client (and other pieces) out into a `plane-common` crate with the parts needed to "consume" Plane as a client, and a crate for Plane itself (in particular, without the database and ACME stuff, which bring in other dependencies that can be hard to wrangle). This looks like a huge PR but there is essentially no net new code here; files are just moved around. A few notes: - I got rid of `plane-dynamic`; it was a hack to make tests compile faster but it should be less necessary now that we have broken up Plane into several crates. - Roughly, the criteria for "what goes in common" is "the client and everything it depends on". `plane` depends on `plane-common`, but `plane-common` does NOT depend on `plane`, so things like `ExponentialBackoff` (used by the client to manage reconnects) go in `plane-common`. Todo: - [x] get `test_get_metrics` and `backend_lifecycle` tests to pass. - [x] rename to `plane-common`? - [x] p2 PR for refactor and ensure p2 integration tests pass --- Cargo.lock | 383 +++++++++++++++--- Cargo.toml | 2 +- common/Cargo.toml | 29 ++ {plane => common}/build.rs | 0 .../src}/controller_address.rs | 0 common/src/exponential_backoff.rs | 68 ++++ plane/src/client/mod.rs => common/src/lib.rs | 12 +- {plane => common}/src/log_types.rs | 11 +- {plane => common}/src/names.rs | 24 +- {plane => common}/src/protocol.rs | 71 +++- {plane => common}/src/serialization.rs | 0 {plane/src/client => common/src}/sse.rs | 2 +- {plane => common}/src/typed_socket/client.rs | 9 +- {plane => common}/src/typed_socket/mod.rs | 4 +- {plane => common}/src/typed_socket/server.rs | 28 +- {plane => common}/src/types/backend_state.rs | 11 +- {plane => common}/src/types/mod.rs | 2 +- common/src/util.rs | 24 ++ common/src/version.rs | 22 + plane/Cargo.toml | 1 + plane/plane-dynamic/Cargo.toml | 11 - plane/plane-dynamic/README.md | 3 - plane/plane-dynamic/src/lib.rs | 1 - plane/plane-tests/Cargo.toml | 3 +- plane/plane-tests/tests/backend_actions.rs | 7 +- .../tests/backend_lifecycle_docker.rs | 4 +- .../tests/backend_lifecycle_socket.rs | 10 +- .../tests/backend_status_in_response.rs | 2 +- plane/plane-tests/tests/cert_manager.rs | 13 +- plane/plane-tests/tests/common/mod.rs | 2 +- plane/plane-tests/tests/common/proxy_mock.rs | 4 +- plane/plane-tests/tests/common/test_env.rs | 6 +- plane/plane-tests/tests/dns_api.rs | 2 +- plane/plane-tests/tests/docker_command.rs | 10 +- plane/plane-tests/tests/drone_pools.rs | 2 +- plane/plane-tests/tests/forward_auth.rs | 2 +- plane/plane-tests/tests/metrics.rs | 10 +- plane/plane-tests/tests/proxy.rs | 2 +- plane/plane-tests/tests/proxy_cert_lease.rs | 2 +- .../tests/proxy_connection_monitor.rs | 2 +- plane/plane-tests/tests/proxy_cors.rs | 2 +- plane/plane-tests/tests/proxy_headers.rs | 2 +- .../plane-tests/tests/proxy_server_header.rs | 2 +- plane/plane-tests/tests/reuse_key.rs | 2 +- plane/plane-tests/tests/subdomains.rs | 2 +- plane/plane-tests/tests/volume_mounts.rs | 2 +- plane/src/admin.rs | 13 +- plane/src/bin/db-cli.rs | 5 +- plane/src/controller/backend_state.rs | 16 +- plane/src/controller/cluster_state.rs | 2 +- plane/src/controller/command.rs | 6 +- plane/src/controller/connect.rs | 7 +- plane/src/controller/core.rs | 8 +- plane/src/controller/dns.rs | 8 +- plane/src/controller/drain.rs | 8 +- plane/src/controller/drone.rs | 35 +- plane/src/controller/error.rs | 37 +- plane/src/controller/mod.rs | 18 +- plane/src/controller/proxy.rs | 25 +- plane/src/controller/terminate.rs | 10 +- plane/src/database/acme.rs | 2 +- plane/src/database/backend.rs | 42 +- plane/src/database/backend_actions.rs | 6 +- plane/src/database/backend_key.rs | 4 +- plane/src/database/cluster.rs | 2 +- plane/src/database/connect.rs | 13 +- plane/src/database/controller.rs | 2 +- plane/src/database/drone.rs | 9 +- plane/src/database/mod.rs | 4 +- plane/src/database/node.rs | 8 +- plane/src/database/subscribe.rs | 5 +- plane/src/dns/command.rs | 2 +- plane/src/dns/mod.rs | 13 +- plane/src/dns/name_to_cluster.rs | 5 +- plane/src/drone/backend_manager.rs | 10 +- plane/src/drone/command.rs | 14 +- plane/src/drone/executor.rs | 16 +- plane/src/drone/heartbeat.rs | 6 +- plane/src/drone/key_manager.rs | 6 +- plane/src/drone/mod.rs | 19 +- plane/src/drone/runtime/docker/commands.rs | 12 +- plane/src/drone/runtime/docker/metrics.rs | 2 +- plane/src/drone/runtime/docker/mod.rs | 11 +- plane/src/drone/runtime/docker/types.rs | 17 +- .../src/drone/runtime/docker/wait_backend.rs | 2 +- plane/src/drone/runtime/mod.rs | 11 +- plane/src/drone/runtime/unix_socket/mod.rs | 10 +- plane/src/drone/state_store.rs | 8 +- plane/src/lib.rs | 29 +- plane/src/main.rs | 3 +- plane/src/proxy/cert_manager.rs | 10 +- plane/src/proxy/cert_pair.rs | 15 +- plane/src/proxy/command.rs | 9 +- plane/src/proxy/connection_monitor.rs | 3 +- plane/src/proxy/mod.rs | 6 +- plane/src/proxy/proxy_connection.rs | 4 +- plane/src/proxy/proxy_server.rs | 2 +- plane/src/proxy/request.rs | 2 +- plane/src/proxy/route_map.rs | 4 +- plane/src/typed_unix_socket/client.rs | 10 +- plane/src/typed_unix_socket/mod.rs | 3 +- plane/src/util.rs | 107 +---- 102 files changed, 893 insertions(+), 586 deletions(-) create mode 100644 common/Cargo.toml rename {plane => common}/build.rs (100%) rename {plane/src/client => common/src}/controller_address.rs (100%) create mode 100644 common/src/exponential_backoff.rs rename plane/src/client/mod.rs => common/src/lib.rs (97%) rename {plane => common}/src/log_types.rs (83%) rename {plane => common}/src/names.rs (93%) rename {plane => common}/src/protocol.rs (79%) rename {plane => common}/src/serialization.rs (100%) rename {plane/src/client => common/src}/sse.rs (99%) rename {plane => common}/src/typed_socket/client.rs (97%) rename {plane => common}/src/typed_socket/mod.rs (98%) rename {plane => common}/src/typed_socket/server.rs (83%) rename {plane => common}/src/types/backend_state.rs (98%) rename {plane => common}/src/types/mod.rs (99%) create mode 100644 common/src/util.rs create mode 100644 common/src/version.rs delete mode 100644 plane/plane-dynamic/Cargo.toml delete mode 100644 plane/plane-dynamic/README.md delete mode 100644 plane/plane-dynamic/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index b4148f77c..660631a1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,9 +128,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "asn1-rs" @@ -156,7 +156,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", "synstructure", ] @@ -168,7 +168,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -190,7 +190,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -201,7 +201,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -254,9 +254,9 @@ dependencies = [ [[package]] name = "axum" -version = "0.7.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ "async-trait", "axum-core", @@ -356,7 +356,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.79", + "syn 2.0.89", "which", ] @@ -494,9 +494,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.19" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -504,9 +504,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.19" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -523,7 +523,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -667,7 +667,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -678,7 +678,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -756,7 +756,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -807,7 +807,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -965,7 +965,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -1298,6 +1298,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1316,12 +1434,23 @@ dependencies = [ [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] @@ -1454,6 +1583,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "lock_api" version = "0.4.12" @@ -1696,7 +1831,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -1800,7 +1935,7 @@ checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -1865,6 +2000,7 @@ dependencies = [ "lru", "openssl", "pem", + "plane-common", "plane-dynamic-proxy", "rand", "reqwest", @@ -1893,10 +2029,29 @@ dependencies = [ ] [[package]] -name = "plane-dynamic" -version = "0.4.9" +name = "plane-common" +version = "0.5.1" dependencies = [ - "plane", + "anyhow", + "async-stream", + "axum", + "bollard", + "chrono", + "clap", + "data-encoding", + "futures-util", + "rand", + "reqwest", + "serde", + "serde_json", + "serde_with", + "thiserror", + "tokio", + "tokio-tungstenite", + "tracing", + "tungstenite", + "url", + "valuable", ] [[package]] @@ -1932,7 +2087,7 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -1948,7 +2103,8 @@ dependencies = [ "http", "http-body-util", "hyper", - "plane-dynamic", + "plane", + "plane-common", "plane-dynamic-proxy", "plane-test-macro", "reqwest", @@ -1985,14 +2141,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ "proc-macro2", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -2152,9 +2308,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.8" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64", "bytes", @@ -2385,29 +2541,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -2433,7 +2589,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -2484,7 +2640,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -2667,7 +2823,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -2690,7 +2846,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.79", + "syn 2.0.89", "tempfile", "tokio", "url", @@ -2803,6 +2959,12 @@ dependencies = [ "url", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "stringprep" version = "0.1.5" @@ -2839,9 +3001,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -2871,7 +3033,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -2925,7 +3087,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -2969,6 +3131,16 @@ dependencies = [ "time-core", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.8.0" @@ -2986,9 +3158,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -3009,7 +3181,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -3184,7 +3356,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", ] [[package]] @@ -3373,12 +3545,12 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna 1.0.3", "percent-encoding", "serde", ] @@ -3389,6 +3561,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -3480,7 +3664,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", "wasm-bindgen-shared", ] @@ -3514,7 +3698,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3797,6 +3981,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "x509-parser" version = "0.16.0" @@ -3823,6 +4019,30 @@ dependencies = [ "time", ] +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -3841,7 +4061,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.89", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", + "synstructure", ] [[package]] @@ -3849,3 +4090,25 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] diff --git a/Cargo.toml b/Cargo.toml index 0e88a01ed..b65095785 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,9 @@ [workspace] resolver = "2" members = [ + "common", "dynamic-proxy", "plane/plane-tests", - "plane/plane-dynamic", "plane", "plane/plane-tests/plane-test-macro", ] diff --git a/common/Cargo.toml b/common/Cargo.toml new file mode 100644 index 000000000..bf2e18512 --- /dev/null +++ b/common/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "plane-common" +version = "0.5.1" +edition = "2021" + +[dependencies] +axum = { version = "0.7.7", features = ["ws"] } +bollard = "0.17.0" +chrono = { version = "0.4.31", features = ["serde"] } +clap = "4.4.10" +data-encoding = "2.4.0" +futures-util = "0.3.29" +rand = "0.8.5" +reqwest = { version = "0.12.8", features = ["json"] } +serde = "1.0.109" +serde_json = "1.0.107" +serde_with = "3.4.0" +thiserror = "1.0.50" +tokio = { version = "1.33.0", features = ["sync"] } +tokio-tungstenite = "0.24.0" +tracing = "0.1.40" +tungstenite = "0.24.0" +url = "2.4.1" +valuable = { version = "0.1.0", features = ["derive"] } + +[dev-dependencies] +anyhow = "1.0.93" +async-stream = "0.3.6" +axum = "0.7.9" diff --git a/plane/build.rs b/common/build.rs similarity index 100% rename from plane/build.rs rename to common/build.rs diff --git a/plane/src/client/controller_address.rs b/common/src/controller_address.rs similarity index 100% rename from plane/src/client/controller_address.rs rename to common/src/controller_address.rs diff --git a/common/src/exponential_backoff.rs b/common/src/exponential_backoff.rs new file mode 100644 index 000000000..88cad790a --- /dev/null +++ b/common/src/exponential_backoff.rs @@ -0,0 +1,68 @@ +use std::time::{Duration, SystemTime}; + +pub struct ExponentialBackoff { + initial_duration_millis: u128, + max_duration: Duration, + defer_duration: Duration, + multiplier: f64, + step: i32, + deferred_reset: Option, +} + +impl ExponentialBackoff { + pub fn new( + initial_duration: Duration, + max_duration: Duration, + multiplier: f64, + defer_duration: Duration, + ) -> Self { + let initial_duration_millis = initial_duration.as_millis(); + + Self { + initial_duration_millis, + max_duration, + multiplier, + step: 0, + defer_duration, + deferred_reset: None, + } + } + + /// Reset the backoff, but only if `wait` is not called again for at least `defer_duration`. + pub fn defer_reset(&mut self) { + self.deferred_reset = Some(SystemTime::now() + self.defer_duration); + } + + pub async fn wait(&mut self) { + if let Some(deferred_reset) = self.deferred_reset { + self.deferred_reset = None; + if SystemTime::now() > deferred_reset { + self.reset(); + return; + } + } + + let duration = self.initial_duration_millis as f64 * self.multiplier.powi(self.step); + let duration = Duration::from_millis(duration as u64); + let duration = duration.min(self.max_duration); + tokio::time::sleep(duration).await; + + self.step += 1; + } + + pub fn reset(&mut self) { + self.deferred_reset = None; + self.step = 0; + } +} + +impl Default for ExponentialBackoff { + fn default() -> Self { + Self::new( + Duration::from_secs(1), + Duration::from_secs(60), + 1.1, + Duration::from_secs(60), + ) + } +} diff --git a/plane/src/client/mod.rs b/common/src/lib.rs similarity index 97% rename from plane/src/client/mod.rs rename to common/src/lib.rs index fdd3b5d5d..1f56398ce 100644 --- a/plane/src/client/mod.rs +++ b/common/src/lib.rs @@ -1,6 +1,5 @@ use self::controller_address::AuthorizedAddress; use crate::{ - controller::{error::ApiError, StatusResponse}, names::{BackendName, DroneName}, protocol::{MessageFromDns, MessageFromDrone, MessageFromProxy}, typed_socket::client::TypedSocketConnector, @@ -9,11 +8,22 @@ use crate::{ ConnectResponse, DrainResult, DronePoolName, RevokeRequest, }, }; +use protocol::{ApiError, StatusResponse}; use reqwest::{Response, StatusCode}; use serde::de::DeserializeOwned; use url::{form_urlencoded, Url}; + pub mod controller_address; +pub mod exponential_backoff; +pub mod log_types; +pub mod names; +pub mod protocol; +pub mod serialization; pub mod sse; +pub mod typed_socket; +pub mod types; +pub mod util; +pub mod version; #[derive(thiserror::Error, Debug)] pub enum PlaneClientError { diff --git a/plane/src/log_types.rs b/common/src/log_types.rs similarity index 83% rename from plane/src/log_types.rs rename to common/src/log_types.rs index 34072dfa1..99267106b 100644 --- a/plane/src/log_types.rs +++ b/common/src/log_types.rs @@ -1,7 +1,6 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; -use std::{net::SocketAddr, time::SystemTime}; -use time::OffsetDateTime; +use std::net::SocketAddr; use valuable::{Tuplable, TupleDef, Valuable, Value, Visit}; // See: https://github.com/tokio-rs/valuable/issues/86#issuecomment-1760446976 @@ -27,14 +26,6 @@ impl Tuplable for LoggableTime { } } -impl From for LoggableTime { - fn from(offset: OffsetDateTime) -> Self { - let t: SystemTime = offset.into(); - let dt: DateTime = t.into(); - Self(dt) - } -} - #[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd)] pub struct BackendAddr(pub SocketAddr); diff --git a/plane/src/names.rs b/common/src/names.rs similarity index 93% rename from plane/src/names.rs rename to common/src/names.rs index ae842adfd..c2fff3ae8 100644 --- a/plane/src/names.rs +++ b/common/src/names.rs @@ -1,4 +1,4 @@ -use crate::{drone::runtime::docker::types::ContainerId, types::NodeKind}; +use crate::types::NodeKind; use clap::error::ErrorKind; use serde::{Deserialize, Serialize}; use std::fmt::{Debug, Display}; @@ -17,8 +17,9 @@ pub enum NameError { InvalidCharacter(char, usize), #[error( - "too long ({0} characters; max is {} including prefix)", - MAX_NAME_LENGTH + "too long ({length} characters; max is {max} including prefix)", + length = "{0}", + max = MAX_NAME_LENGTH )] TooLong(usize), } @@ -163,17 +164,18 @@ entity_name!(DroneName, Some("dr")); entity_name!(AcmeDnsServerName, Some("ns")); entity_name!(BackendActionName, Some("ak")); -impl TryFrom for BackendName { - type Error = NameError; - - fn try_from(value: ContainerId) -> Result { - value - .as_str() +impl BackendName { + pub fn from_container_id(container_id: String) -> Result { + container_id .strip_prefix("plane-") - .ok_or_else(|| NameError::InvalidPrefix(value.to_string(), "plane-".to_string()))? + .ok_or_else(|| NameError::InvalidPrefix(container_id.clone(), "plane-".to_string()))? .to_string() .try_into() } + + pub fn to_container_id(&self) -> String { + format!("plane-{}", self) + } } pub trait NodeName: Name { @@ -294,7 +296,7 @@ mod tests { #[test] fn test_backend_name_from_invalid_container_id() { - let container_id = ContainerId::from("invalid-123".to_string()); + let container_id = "invalid-123".to_string(); assert_eq!( Err(NameError::InvalidPrefix( "invalid-123".to_string(), diff --git a/plane/src/protocol.rs b/common/src/protocol.rs similarity index 79% rename from plane/src/protocol.rs rename to common/src/protocol.rs index 48332fb74..8fe5463cc 100644 --- a/plane/src/protocol.rs +++ b/common/src/protocol.rs @@ -1,16 +1,45 @@ +use std::fmt::Display; + use crate::{ - database::backend::{BackendActionMessage, BackendMetricsMessage}, log_types::{BackendAddr, LoggableTime}, names::{BackendActionName, BackendName}, typed_socket::ChannelMessage, types::{ backend_state::TerminationReason, BackendState, BearerToken, ClusterName, KeyConfig, - SecretToken, Subdomain, TerminationKind, + NodeId, SecretToken, Subdomain, TerminationKind, }, }; use serde::{Deserialize, Serialize}; use serde_json::Value; +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] +pub enum ApiErrorKind { + FailedToAcquireKey, + KeyUnheldNoSpawnConfig, + KeyHeldUnhealthy, + KeyHeld, + NoDroneAvailable, + FailedToRemoveKey, + DatabaseError, + NoClusterProvided, + NotFound, + InvalidClusterName, + Other, +} + +#[derive(thiserror::Error, Debug, Serialize, Deserialize)] +pub struct ApiError { + pub id: String, + pub kind: ApiErrorKind, + pub message: String, +} + +impl Display for ApiError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self) + } +} + #[derive(Serialize, Deserialize, Debug, Clone, valuable::Valuable, PartialEq)] pub struct KeyDeadlines { /// When the key should be renewed. @@ -132,6 +161,29 @@ pub enum MessageFromDrone { RenewKey(RenewKeyRequest), } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct BackendMetricsMessage { + pub backend_id: BackendName, + /// Memory used by backend excluding inactive file cache, same as use shown by docker stats + /// ref: https://github.com/docker/cli/blob/master/cli/command/container/stats_helpers.go#L227C45-L227C45 + pub mem_used: u64, + /// Memory used by backend in bytes + /// (calculated using kernel memory used by cgroup + page cache memory used by cgroup) + pub mem_total: u64, + /// Active memory (non reclaimable) + pub mem_active: u64, + /// Inactive memory (reclaimable) + pub mem_inactive: u64, + /// Unevictable memory (mlock etc) + pub mem_unevictable: u64, + /// The backend's memory limit + pub mem_limit: u64, + /// Nanoseconds of CPU used by backend since last message + pub cpu_used: u64, + /// Total CPU nanoseconds for system since last message + pub sys_cpu: u64, +} + impl ChannelMessage for MessageFromDrone { type Reply = MessageToDrone; } @@ -146,6 +198,14 @@ pub struct RenewKeyResponse { pub deadlines: Option, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BackendActionMessage { + pub action_id: BackendActionName, + pub backend_id: BackendName, + pub drone_id: NodeId, + pub action: BackendAction, +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub enum MessageToDrone { Action(BackendActionMessage), @@ -263,3 +323,10 @@ pub enum MessageToDns { impl ChannelMessage for MessageToDns { type Reply = MessageFromDns; } + +#[derive(Serialize, Deserialize, Debug)] +pub struct StatusResponse { + pub status: String, + pub version: String, + pub hash: String, +} diff --git a/plane/src/serialization.rs b/common/src/serialization.rs similarity index 100% rename from plane/src/serialization.rs rename to common/src/serialization.rs diff --git a/plane/src/client/sse.rs b/common/src/sse.rs similarity index 99% rename from plane/src/client/sse.rs rename to common/src/sse.rs index 2651ece28..fd104308f 100644 --- a/plane/src/client/sse.rs +++ b/common/src/sse.rs @@ -1,5 +1,5 @@ use super::PlaneClientError; -use crate::util::ExponentialBackoff; +use crate::exponential_backoff::ExponentialBackoff; use reqwest::{ header::{HeaderValue, ACCEPT, CONNECTION}, Client, Response, diff --git a/plane/src/typed_socket/client.rs b/common/src/typed_socket/client.rs similarity index 97% rename from plane/src/typed_socket/client.rs rename to common/src/typed_socket/client.rs index 10393c026..6a26856a1 100644 --- a/plane/src/typed_socket/client.rs +++ b/common/src/typed_socket/client.rs @@ -1,8 +1,9 @@ use super::{ChannelMessage, Handshake, SocketAction, TypedSocket}; -use crate::client::controller_address::AuthorizedAddress; -use crate::client::PlaneClientError; +use crate::controller_address::AuthorizedAddress; +use crate::exponential_backoff::ExponentialBackoff; use crate::names::NodeName; -use crate::{plane_version_info, util::ExponentialBackoff}; +use crate::version::plane_version_info; +use crate::PlaneClientError; use futures_util::{SinkExt, StreamExt}; use std::marker::PhantomData; use tokio::net::TcpStream; @@ -191,7 +192,7 @@ async fn new_client( #[cfg(test)] mod test { - use crate::client::controller_address::AuthorizedAddress; + use crate::controller_address::AuthorizedAddress; #[test] fn test_url_no_token() { diff --git a/plane/src/typed_socket/mod.rs b/common/src/typed_socket/mod.rs similarity index 98% rename from plane/src/typed_socket/mod.rs rename to common/src/typed_socket/mod.rs index e4159a1e3..0e8ff2fe3 100644 --- a/plane/src/typed_socket/mod.rs +++ b/common/src/typed_socket/mod.rs @@ -1,5 +1,5 @@ -use crate::client::PlaneClientError; -use crate::PlaneVersionInfo; +use crate::version::PlaneVersionInfo; +use crate::PlaneClientError; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use std::fmt::Debug; diff --git a/plane/src/typed_socket/server.rs b/common/src/typed_socket/server.rs similarity index 83% rename from plane/src/typed_socket/server.rs rename to common/src/typed_socket/server.rs index dcfb103b0..2a13555bc 100644 --- a/plane/src/typed_socket/server.rs +++ b/common/src/typed_socket/server.rs @@ -1,9 +1,23 @@ use super::{ChannelMessage, Handshake, SocketAction, TypedSocket}; -use crate::plane_version_info; -use anyhow::{anyhow, Context, Result}; +use crate::version::plane_version_info; use axum::extract::ws::{CloseFrame, Message, WebSocket}; use tokio::sync::mpsc::{Receiver, Sender}; +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Handshake message was not text.")] + HandshakeNotText, + + #[error("Socket closed before handshake received.")] + SocketClosedBeforeHandshake, + + #[error("Failed to parse message.")] + ParseMessage(#[from] serde_json::Error), + + #[error("Failed to send message on websocket.")] + SendMessage(#[from] axum::Error), +} + pub async fn handle_messages( mut messages_to_send: Receiver>, messages_received: Sender, @@ -65,20 +79,20 @@ pub async fn handle_messages( pub async fn new_server( mut ws: WebSocket, name: String, -) -> Result> { +) -> Result, Error> { let msg = ws .recv() .await - .ok_or_else(|| anyhow!("Socket closed before handshake received."))??; + .ok_or(Error::SocketClosedBeforeHandshake)? + .map_err(Error::from)?; let msg = match msg { Message::Text(msg) => msg, msg => { tracing::warn!("Received ignored message: {:?}", msg); - return Err(anyhow!("Handshake message was not text.")); + return Err(Error::HandshakeNotText); } }; - let remote_handshake: Handshake = - serde_json::from_str(&msg).context("Parsing handshake from client.")?; + let remote_handshake: Handshake = serde_json::from_str(&msg).map_err(Error::ParseMessage)?; tracing::info!( client_version = %remote_handshake.version.version, client_hash = %remote_handshake.version.git_hash, diff --git a/plane/src/types/backend_state.rs b/common/src/types/backend_state.rs similarity index 98% rename from plane/src/types/backend_state.rs rename to common/src/types/backend_state.rs index 32dea5040..8fca9bda4 100644 --- a/plane/src/types/backend_state.rs +++ b/common/src/types/backend_state.rs @@ -1,7 +1,4 @@ -use crate::{ - database::backend::BackendRow, - log_types::{BackendAddr, LoggableTime}, -}; +use crate::log_types::{BackendAddr, LoggableTime}; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -454,9 +451,3 @@ impl BackendStatusStreamEntry { } } } - -impl From for BackendStatusStreamEntry { - fn from(row: BackendRow) -> Self { - Self::from_state(row.state, row.last_status_time) - } -} diff --git a/plane/src/types/mod.rs b/common/src/types/mod.rs similarity index 99% rename from plane/src/types/mod.rs rename to common/src/types/mod.rs index 66f072f4b..502960bcb 100644 --- a/plane/src/types/mod.rs +++ b/common/src/types/mod.rs @@ -1,7 +1,7 @@ use crate::{ - client::PlaneClient, names::{AnyNodeName, BackendName, ControllerName, DroneName}, util::{random_prefixed_string, random_token}, + PlaneClient, }; pub use backend_state::{BackendState, BackendStatus, TerminationKind, TerminationReason}; use bollard::auth::DockerCredentials; diff --git a/common/src/util.rs b/common/src/util.rs new file mode 100644 index 000000000..0bfda8890 --- /dev/null +++ b/common/src/util.rs @@ -0,0 +1,24 @@ +use rand::{distributions::Uniform, prelude::Distribution, Rng}; + +const ALLOWED_CHARS: &str = "abcdefghijklmnopqrstuvwxyz0123456789"; + +pub fn random_string() -> String { + let range = Uniform::new(0, ALLOWED_CHARS.len()); + let mut rng = rand::thread_rng(); + + range + .sample_iter(&mut rng) + .take(14) + .map(|i| ALLOWED_CHARS.chars().nth(i).expect("Index is always valid")) + .collect() +} + +pub fn random_token() -> String { + let mut token = [0u8; 32]; + rand::thread_rng().fill(&mut token); + data_encoding::BASE64URL_NOPAD.encode(&token) +} + +pub fn random_prefixed_string(prefix: &str) -> String { + format!("{}-{}", prefix, random_string()) +} diff --git a/common/src/version.rs b/common/src/version.rs new file mode 100644 index 000000000..e596a54a2 --- /dev/null +++ b/common/src/version.rs @@ -0,0 +1,22 @@ +use serde::{Deserialize, Serialize}; + +/// The version of the plane binary from Cargo.toml. +pub const PLANE_VERSION: &str = env!("CARGO_PKG_VERSION"); + +/// The git hash of the plane binary (passed from build.rs) +pub const PLANE_GIT_HASH: &str = env!("GIT_HASH"); + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +pub struct PlaneVersionInfo { + pub version: String, + pub git_hash: String, +} + +pub fn plane_version_info() -> PlaneVersionInfo { + PlaneVersionInfo { + version: PLANE_VERSION.to_string(), + git_hash: PLANE_GIT_HASH.to_string(), + } +} + +pub const SERVER_NAME: &str = concat!("Plane/", env!("CARGO_PKG_VERSION"), "-", env!("GIT_HASH")); diff --git a/plane/Cargo.toml b/plane/Cargo.toml index 10b50c276..fea9d632d 100644 --- a/plane/Cargo.toml +++ b/plane/Cargo.toml @@ -29,6 +29,7 @@ hyper-util = { version = "0.1.9", features = ["client", "client-legacy", "http1" lru = "0.12.1" openssl = "0.10.66" pem = "3.0.2" +plane-common = { path="../common", version = "0.5.1" } plane-dynamic-proxy = { path="../dynamic-proxy", version = "0.5.1" } rand = "0.8.5" reqwest = { version = "0.12.8", features = ["json", "rustls-tls"], default-features = false } diff --git a/plane/plane-dynamic/Cargo.toml b/plane/plane-dynamic/Cargo.toml deleted file mode 100644 index 15c07e868..000000000 --- a/plane/plane-dynamic/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "plane-dynamic" -version = "0.4.9" -edition = "2021" -publish = false - -[dependencies] -plane = { path = ".." } - -[lib] -crate-type = ["dylib"] diff --git a/plane/plane-dynamic/README.md b/plane/plane-dynamic/README.md deleted file mode 100644 index aec657b75..000000000 --- a/plane/plane-dynamic/README.md +++ /dev/null @@ -1,3 +0,0 @@ -This is a dynamically-linked version of the Plane library. It is only used for tests. - -Using a dynamically-linked library for tests improves the speed of recompilation. diff --git a/plane/plane-dynamic/src/lib.rs b/plane/plane-dynamic/src/lib.rs deleted file mode 100644 index 2cce60daf..000000000 --- a/plane/plane-dynamic/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -pub use plane::*; diff --git a/plane/plane-tests/Cargo.toml b/plane/plane-tests/Cargo.toml index fbc322229..5e13cc98c 100644 --- a/plane/plane-tests/Cargo.toml +++ b/plane/plane-tests/Cargo.toml @@ -14,7 +14,8 @@ futures-util = "0.3.29" http = "1.1.0" http-body-util = "0.1.2" hyper = { version = "1.4.1", features = ["server"] } -plane = { path = "../plane-dynamic", package = "plane-dynamic" } +plane = { path = "../", package = "plane" } +plane-common = { path="../../common", version = "0.5.1" } plane-dynamic-proxy = { path = "../../dynamic-proxy" } plane-test-macro = { path = "plane-test-macro" } reqwest = { version = "0.12.8", features = ["json", "rustls-tls"], default-features = false } diff --git a/plane/plane-tests/tests/backend_actions.rs b/plane/plane-tests/tests/backend_actions.rs index 952ad0837..7e25f765d 100644 --- a/plane/plane-tests/tests/backend_actions.rs +++ b/plane/plane-tests/tests/backend_actions.rs @@ -1,16 +1,15 @@ use chrono::Utc; use common::test_env::TestEnvironment; use hyper::StatusCode; -use plane::{ - client::PlaneClientError, - database::backend::BackendActionMessage, +use plane_common::{ log_types::LoggableTime, names::{DroneName, Name}, - protocol::{BackendAction, Heartbeat, MessageFromDrone, MessageToDrone}, + protocol::{BackendAction, BackendActionMessage, Heartbeat, MessageFromDrone, MessageToDrone}, types::{ ClusterName, ConnectRequest, ConnectResponse, DockerExecutorConfig, DronePoolName, SpawnConfig, }, + PlaneClientError, }; use plane_test_macro::plane_test; use std::time::Duration; diff --git a/plane/plane-tests/tests/backend_lifecycle_docker.rs b/plane/plane-tests/tests/backend_lifecycle_docker.rs index 46274efb0..08c22af8f 100644 --- a/plane/plane-tests/tests/backend_lifecycle_docker.rs +++ b/plane/plane-tests/tests/backend_lifecycle_docker.rs @@ -1,6 +1,6 @@ use crate::common::timeout::WithTimeout; use common::test_env::TestEnvironment; -use plane::{ +use plane_common::{ names::{Name, ProxyName}, protocol::{MessageFromProxy, MessageToProxy, RouteInfoRequest, RouteInfoResponse}, types::{ @@ -15,7 +15,7 @@ use std::collections::HashMap; mod common; #[plane_test] -async fn backend_lifecycle(env: TestEnvironment) { +async fn backend_lifecycle_docker(env: TestEnvironment) { let db = env.db().await; let controller = env.controller().await; let client = controller.client(); diff --git a/plane/plane-tests/tests/backend_lifecycle_socket.rs b/plane/plane-tests/tests/backend_lifecycle_socket.rs index 95e3665e2..15fcbd001 100644 --- a/plane/plane-tests/tests/backend_lifecycle_socket.rs +++ b/plane/plane-tests/tests/backend_lifecycle_socket.rs @@ -1,10 +1,10 @@ use crate::common::timeout::WithTimeout; use common::test_env::TestEnvironment; -use plane::{ - drone::runtime::{ - docker::{types::ContainerId, SpawnResult, TerminateEvent}, - unix_socket::{MessageToClient, MessageToServer}, - }, +use plane::drone::runtime::{ + docker::{types::ContainerId, SpawnResult, TerminateEvent}, + unix_socket::{MessageToClient, MessageToServer}, +}; +use plane_common::{ names::{Name, ProxyName}, protocol::{MessageFromProxy, MessageToProxy, RouteInfoRequest, RouteInfoResponse}, types::{ diff --git a/plane/plane-tests/tests/backend_status_in_response.rs b/plane/plane-tests/tests/backend_status_in_response.rs index ebd7bfd63..58c731dc2 100644 --- a/plane/plane-tests/tests/backend_status_in_response.rs +++ b/plane/plane-tests/tests/backend_status_in_response.rs @@ -1,6 +1,6 @@ use crate::common::timeout::WithTimeout; use common::test_env::TestEnvironment; -use plane::types::{ +use plane_common::types::{ BackendStatus, ConnectRequest, DockerExecutorConfig, DronePoolName, KeyConfig, PullPolicy, ResourceLimits, SpawnConfig, }; diff --git a/plane/plane-tests/tests/cert_manager.rs b/plane/plane-tests/tests/cert_manager.rs index 90042cfae..da0713d91 100644 --- a/plane/plane-tests/tests/cert_manager.rs +++ b/plane/plane-tests/tests/cert_manager.rs @@ -1,15 +1,12 @@ -use std::sync::Arc; - use crate::common::timeout::WithTimeout; use common::test_env::TestEnvironment; -use plane::{ - names::{Name, ProxyName}, - proxy::{ - cert_manager::watcher_manager_pair, proxy_connection::ProxyConnection, - proxy_server::ProxyState, AcmeConfig, AcmeEabConfiguration, - }, +use plane::proxy::{ + cert_manager::watcher_manager_pair, proxy_connection::ProxyConnection, + proxy_server::ProxyState, AcmeConfig, AcmeEabConfiguration, }; +use plane_common::names::{Name, ProxyName}; use plane_test_macro::plane_test; +use std::sync::Arc; mod common; diff --git a/plane/plane-tests/tests/common/mod.rs b/plane/plane-tests/tests/common/mod.rs index 8ea45bdce..8e207dd43 100644 --- a/plane/plane-tests/tests/common/mod.rs +++ b/plane/plane-tests/tests/common/mod.rs @@ -1,6 +1,6 @@ use self::{test_env::TestEnvironment, timeout::WithTimeout}; use futures_util::Future; -use plane::{client::PlaneClient, names::BackendName, types::BackendStatus}; +use plane_common::{names::BackendName, types::BackendStatus, PlaneClient}; use std::{panic::AssertUnwindSafe, time::Duration}; use tokio::time::timeout; diff --git a/plane/plane-tests/tests/common/proxy_mock.rs b/plane/plane-tests/tests/common/proxy_mock.rs index 7ac1375aa..cef3aa815 100644 --- a/plane/plane-tests/tests/common/proxy_mock.rs +++ b/plane/plane-tests/tests/common/proxy_mock.rs @@ -1,7 +1,7 @@ -use plane::{ +use plane::proxy::{connection_monitor::BackendEntry, proxy_server::ProxyState}; +use plane_common::{ names::BackendName, protocol::{RouteInfoRequest, RouteInfoResponse}, - proxy::{connection_monitor::BackendEntry, proxy_server::ProxyState}, }; use plane_dynamic_proxy::server::{HttpsConfig, SimpleHttpServer}; use std::net::SocketAddr; diff --git a/plane/plane-tests/tests/common/test_env.rs b/plane/plane-tests/tests/common/test_env.rs index fe8a46217..ef006ac0e 100644 --- a/plane/plane-tests/tests/common/test_env.rs +++ b/plane/plane-tests/tests/common/test_env.rs @@ -4,7 +4,6 @@ use super::{ }; use chrono::Duration; use plane::{ - client::PlaneClient, controller::ControllerServer, database::PlaneDatabase, dns::run_dns_with_listener, @@ -15,14 +14,17 @@ use plane::{ }, Drone, DroneConfig, ExecutorConfig, }, - names::{AcmeDnsServerName, ControllerName, DroneName, Name, ProxyName}, proxy::{ cert_manager::watcher_manager_pair, proxy_connection::ProxyConnection, proxy_server::ProxyState, AcmeEabConfiguration, }, typed_unix_socket::{server::TypedUnixSocketServer, WrappedMessage}, +}; +use plane_common::{ + names::{AcmeDnsServerName, ControllerName, DroneName, Name, ProxyName}, types::{ClusterName, DronePoolName}, util::random_string, + PlaneClient, }; use plane_dynamic_proxy::server::{HttpsConfig, SimpleHttpServer}; use std::{ diff --git a/plane/plane-tests/tests/dns_api.rs b/plane/plane-tests/tests/dns_api.rs index c886b0522..5892eadf1 100644 --- a/plane/plane-tests/tests/dns_api.rs +++ b/plane/plane-tests/tests/dns_api.rs @@ -1,5 +1,5 @@ use common::test_env::TestEnvironment; -use plane::{ +use plane_common::{ names::{AcmeDnsServerName, Name, ProxyName}, protocol::{ CertManagerRequest, CertManagerResponse, MessageFromDns, MessageFromProxy, MessageToDns, diff --git a/plane/plane-tests/tests/docker_command.rs b/plane/plane-tests/tests/docker_command.rs index eb63243a1..e89bcbb48 100644 --- a/plane/plane-tests/tests/docker_command.rs +++ b/plane/plane-tests/tests/docker_command.rs @@ -1,11 +1,11 @@ use anyhow::Context; use bollard::container::LogsOptions; use futures_util::TryStreamExt; -use plane::{ - drone::runtime::docker::{ - commands::{get_container_config_from_executor_config, pull_image}, - types::ContainerId, - }, +use plane::drone::runtime::docker::{ + commands::{get_container_config_from_executor_config, pull_image}, + types::ContainerId, +}; +use plane_common::{ names::{BackendName, Name}, types::{DockerExecutorConfig, ResourceLimits}, }; diff --git a/plane/plane-tests/tests/drone_pools.rs b/plane/plane-tests/tests/drone_pools.rs index 0929d6cdf..1e4126141 100644 --- a/plane/plane-tests/tests/drone_pools.rs +++ b/plane/plane-tests/tests/drone_pools.rs @@ -1,6 +1,6 @@ use crate::common::wait_until_backend_terminated; use common::test_env::TestEnvironment; -use plane::types::{ +use plane_common::types::{ ConnectRequest, DockerExecutorConfig, DronePoolName, KeyConfig, PullPolicy, ResourceLimits, SpawnConfig, }; diff --git a/plane/plane-tests/tests/forward_auth.rs b/plane/plane-tests/tests/forward_auth.rs index 1d32db1f0..b30c81b63 100644 --- a/plane/plane-tests/tests/forward_auth.rs +++ b/plane/plane-tests/tests/forward_auth.rs @@ -1,5 +1,5 @@ use common::{auth_mock::MockAuthServer, test_env::TestEnvironment}; -use plane::client::{PlaneClient, PlaneClientError}; +use plane_common::{PlaneClient, PlaneClientError}; use plane_test_macro::plane_test; use reqwest::StatusCode; diff --git a/plane/plane-tests/tests/metrics.rs b/plane/plane-tests/tests/metrics.rs index c1c14a4cd..47d359b5a 100644 --- a/plane/plane-tests/tests/metrics.rs +++ b/plane/plane-tests/tests/metrics.rs @@ -1,10 +1,10 @@ use common::test_env::TestEnvironment; use common::timeout::WithTimeout; -use plane::{ - drone::{ - runtime::docker::{DockerRuntime, DockerRuntimeConfig}, - runtime::Runtime, - }, +use plane::drone::{ + runtime::docker::{DockerRuntime, DockerRuntimeConfig}, + runtime::Runtime, +}; +use plane_common::{ names::{BackendName, Name}, types::DockerExecutorConfig, }; diff --git a/plane/plane-tests/tests/proxy.rs b/plane/plane-tests/tests/proxy.rs index 7b815a920..ced6df0a8 100644 --- a/plane/plane-tests/tests/proxy.rs +++ b/plane/plane-tests/tests/proxy.rs @@ -4,7 +4,7 @@ use common::{ simple_axum_server::{RequestInfo, SimpleAxumServer}, test_env::TestEnvironment, }; -use plane::{ +use plane_common::{ log_types::BackendAddr, names::{BackendName, Name}, protocol::{RouteInfo, RouteInfoResponse}, diff --git a/plane/plane-tests/tests/proxy_cert_lease.rs b/plane/plane-tests/tests/proxy_cert_lease.rs index 233cdbe06..17b33c084 100644 --- a/plane/plane-tests/tests/proxy_cert_lease.rs +++ b/plane/plane-tests/tests/proxy_cert_lease.rs @@ -1,5 +1,5 @@ use common::test_env::TestEnvironment; -use plane::{ +use plane_common::{ names::{Name, ProxyName}, protocol::{CertManagerRequest, CertManagerResponse, MessageFromProxy, MessageToProxy}, }; diff --git a/plane/plane-tests/tests/proxy_connection_monitor.rs b/plane/plane-tests/tests/proxy_connection_monitor.rs index fb659da69..b3fc737a0 100644 --- a/plane/plane-tests/tests/proxy_connection_monitor.rs +++ b/plane/plane-tests/tests/proxy_connection_monitor.rs @@ -3,7 +3,7 @@ use common::{ simple_axum_server::SimpleAxumServer, test_env::TestEnvironment, websocket_echo_server::WebSocketEchoServer, }; -use plane::{ +use plane_common::{ log_types::BackendAddr, names::{BackendName, Name}, protocol::{RouteInfo, RouteInfoResponse}, diff --git a/plane/plane-tests/tests/proxy_cors.rs b/plane/plane-tests/tests/proxy_cors.rs index f4a5d5ff9..504da8dad 100644 --- a/plane/plane-tests/tests/proxy_cors.rs +++ b/plane/plane-tests/tests/proxy_cors.rs @@ -2,7 +2,7 @@ use common::{ localhost_resolver::localhost_client, proxy_mock::MockProxy, simple_axum_server::SimpleAxumServer, test_env::TestEnvironment, }; -use plane::{ +use plane_common::{ log_types::BackendAddr, names::{BackendName, Name}, protocol::{RouteInfo, RouteInfoResponse}, diff --git a/plane/plane-tests/tests/proxy_headers.rs b/plane/plane-tests/tests/proxy_headers.rs index e2e32c226..f734269dd 100644 --- a/plane/plane-tests/tests/proxy_headers.rs +++ b/plane/plane-tests/tests/proxy_headers.rs @@ -4,7 +4,7 @@ use common::{ simple_axum_server::{RequestInfo, SimpleAxumServer}, test_env::TestEnvironment, }; -use plane::{ +use plane_common::{ log_types::BackendAddr, names::{BackendName, Name}, protocol::{RouteInfo, RouteInfoResponse}, diff --git a/plane/plane-tests/tests/proxy_server_header.rs b/plane/plane-tests/tests/proxy_server_header.rs index 00c22567e..71feb1eb1 100644 --- a/plane/plane-tests/tests/proxy_server_header.rs +++ b/plane/plane-tests/tests/proxy_server_header.rs @@ -2,7 +2,7 @@ use common::{ localhost_resolver::localhost_client, proxy_mock::MockProxy, simple_axum_server::SimpleAxumServer, test_env::TestEnvironment, }; -use plane::{ +use plane_common::{ log_types::BackendAddr, names::{BackendName, Name}, protocol::{RouteInfo, RouteInfoResponse}, diff --git a/plane/plane-tests/tests/reuse_key.rs b/plane/plane-tests/tests/reuse_key.rs index 95ee43c5a..82951b262 100644 --- a/plane/plane-tests/tests/reuse_key.rs +++ b/plane/plane-tests/tests/reuse_key.rs @@ -1,6 +1,6 @@ use crate::common::wait_until_backend_terminated; use common::test_env::TestEnvironment; -use plane::types::{ +use plane_common::types::{ ConnectRequest, DockerExecutorConfig, DronePoolName, KeyConfig, PullPolicy, ResourceLimits, SpawnConfig, }; diff --git a/plane/plane-tests/tests/subdomains.rs b/plane/plane-tests/tests/subdomains.rs index 29551cf76..2b6fe0186 100644 --- a/plane/plane-tests/tests/subdomains.rs +++ b/plane/plane-tests/tests/subdomains.rs @@ -1,5 +1,5 @@ use crate::common::{test_env::TestEnvironment, wait_until_backend_terminated}; -use plane::types::{ +use plane_common::types::{ ConnectRequest, DockerExecutorConfig, DronePoolName, PullPolicy, ResourceLimits, SpawnConfig, Subdomain, }; diff --git a/plane/plane-tests/tests/volume_mounts.rs b/plane/plane-tests/tests/volume_mounts.rs index 1300337ce..272a8fb59 100644 --- a/plane/plane-tests/tests/volume_mounts.rs +++ b/plane/plane-tests/tests/volume_mounts.rs @@ -1,6 +1,6 @@ use crate::common::test_env::TestEnvironment; use crate::common::wait_until_backend_terminated; -use plane::types::{ +use plane_common::types::{ ConnectRequest, DockerExecutorConfig, DronePoolName, KeyConfig, Mount, PullPolicy, ResourceLimits, SpawnConfig, }; diff --git a/plane/src/admin.rs b/plane/src/admin.rs index 432bfd724..2282b4411 100644 --- a/plane/src/admin.rs +++ b/plane/src/admin.rs @@ -1,17 +1,18 @@ -use crate::{ - client::{sse::SseStream, PlaneClient, PlaneClientError}, +use chrono::Duration; +use clap::{Parser, Subcommand}; +use colored::Colorize; +use plane_common::{ names::{BackendName, DroneName, Name, ProxyName}, protocol::{CertManagerRequest, CertManagerResponse, MessageFromProxy, MessageToProxy}, + sse::SseStream, types::{ backend_state::BackendStatusStreamEntry, BackendStatus, ClusterName, ClusterState, ConnectRequest, DockerExecutorConfig, DronePoolName, KeyConfig, Mount, NodeState, SpawnConfig, Subdomain, }, - PLANE_GIT_HASH, PLANE_VERSION, + version::{PLANE_GIT_HASH, PLANE_VERSION}, + PlaneClient, PlaneClientError, }; -use chrono::Duration; -use clap::{Parser, Subcommand}; -use colored::Colorize; use std::path::PathBuf; use url::Url; diff --git a/plane/src/bin/db-cli.rs b/plane/src/bin/db-cli.rs index c60b5491c..f42bb5fe1 100644 --- a/plane/src/bin/db-cli.rs +++ b/plane/src/bin/db-cli.rs @@ -2,9 +2,8 @@ use clap::{Parser, Subcommand}; use colored::{self, Colorize}; -use plane::{ - database::connect, - init_tracing::init_tracing, +use plane::{database::connect, init_tracing::init_tracing}; +use plane_common::{ names::{BackendName, DroneName}, types::{BackendState, BackendStatus, ClusterName, TerminationReason}, }; diff --git a/plane/src/controller/backend_state.rs b/plane/src/controller/backend_state.rs index 3bff18389..53ea892cb 100644 --- a/plane/src/controller/backend_state.rs +++ b/plane/src/controller/backend_state.rs @@ -1,8 +1,6 @@ +use crate::database::backend::BackendRow; + use super::{core::Controller, error::IntoApiError}; -use crate::{ - names::BackendName, - types::{backend_state::BackendStatusStreamEntry, BackendStatus}, -}; use axum::{ extract::{Path, State}, http::HeaderMap, @@ -13,8 +11,18 @@ use axum::{ Json, }; use futures_util::{Stream, StreamExt}; +use plane_common::{ + names::BackendName, + types::{backend_state::BackendStatusStreamEntry, BackendStatus}, +}; use std::convert::Infallible; +impl From for BackendStatusStreamEntry { + fn from(row: BackendRow) -> Self { + Self::from_state(row.state, row.last_status_time) + } +} + async fn backend_status( controller: &Controller, backend_id: &BackendName, diff --git a/plane/src/controller/cluster_state.rs b/plane/src/controller/cluster_state.rs index f57cb4323..affe1736b 100644 --- a/plane/src/controller/cluster_state.rs +++ b/plane/src/controller/cluster_state.rs @@ -1,10 +1,10 @@ use super::{core::Controller, error::IntoApiError}; -use crate::types::{ClusterName, ClusterState}; use axum::{ extract::{Path, State}, response::Response, Json, }; +use plane_common::types::{ClusterName, ClusterState}; pub async fn handle_cluster_state( Path(cluster_name): Path, diff --git a/plane/src/controller/command.rs b/plane/src/controller/command.rs index 35d4ae52b..848a1b46a 100644 --- a/plane/src/controller/command.rs +++ b/plane/src/controller/command.rs @@ -1,10 +1,10 @@ use super::ControllerConfig; -use crate::{ +use anyhow::Result; +use clap::Parser; +use plane_common::{ names::{ControllerName, Name}, types::ClusterName, }; -use anyhow::Result; -use clap::Parser; use std::net::IpAddr; use url::Url; diff --git a/plane/src/controller/connect.rs b/plane/src/controller/connect.rs index b46d824c1..419d5c524 100644 --- a/plane/src/controller/connect.rs +++ b/plane/src/controller/connect.rs @@ -1,9 +1,12 @@ -use super::error::{err_to_response, ApiErrorKind}; +use super::error::err_to_response; use super::Controller; use crate::controller::error::IntoApiError; use crate::database::connect::ConnectError; -use crate::types::{ConnectRequest, ConnectResponse, RevokeRequest}; use axum::{extract::State, http::StatusCode, response::Response, Json}; +use plane_common::{ + protocol::ApiErrorKind, + types::{ConnectRequest, ConnectResponse, RevokeRequest}, +}; fn connect_error_to_response(connect_error: &ConnectError) -> Response { match connect_error { diff --git a/plane/src/controller/core.rs b/plane/src/controller/core.rs index bd30fd148..377825a2d 100644 --- a/plane/src/controller/core.rs +++ b/plane/src/controller/core.rs @@ -1,11 +1,11 @@ -use crate::{ - client::PlaneClient, - database::{connect::ConnectError, PlaneDatabase}, +use crate::database::{connect::ConnectError, PlaneDatabase}; +use chrono::{DateTime, Utc}; +use plane_common::{ names::{AnyNodeName, ControllerName}, typed_socket::Handshake, types::{ClusterName, ConnectRequest, ConnectResponse, NodeId}, + PlaneClient, }; -use chrono::{DateTime, Utc}; use std::net::IpAddr; use url::Url; diff --git a/plane/src/controller/dns.rs b/plane/src/controller/dns.rs index 44ee931df..188af517c 100644 --- a/plane/src/controller/dns.rs +++ b/plane/src/controller/dns.rs @@ -1,12 +1,12 @@ use super::Controller; -use crate::{ - protocol::{MessageFromDns, MessageToDns}, - typed_socket::server::new_server, -}; use axum::{ extract::{ws::WebSocket, ConnectInfo, State, WebSocketUpgrade}, response::IntoResponse, }; +use plane_common::{ + protocol::{MessageFromDns, MessageToDns}, + typed_socket::server::new_server, +}; use std::net::{IpAddr, SocketAddr}; use valuable::Valuable; diff --git a/plane/src/controller/drain.rs b/plane/src/controller/drain.rs index 4dd74f6c9..42b6c5cc0 100644 --- a/plane/src/controller/drain.rs +++ b/plane/src/controller/drain.rs @@ -1,13 +1,13 @@ use super::{core::Controller, error::IntoApiError}; -use crate::{ - names::DroneName, - types::{ClusterName, DrainResult}, -}; use axum::{ extract::{Path, State}, response::Response, Json, }; +use plane_common::{ + names::DroneName, + types::{ClusterName, DrainResult}, +}; async fn drain( controller: &Controller, diff --git a/plane/src/controller/drone.rs b/plane/src/controller/drone.rs index af2919c36..180e34f04 100644 --- a/plane/src/controller/drone.rs +++ b/plane/src/controller/drone.rs @@ -1,28 +1,19 @@ -use super::{error::ApiErrorKind, Controller}; -use crate::{ - controller::error::IntoApiError, - database::{ - backend::BackendActionMessage, - backend_key::{ - KEY_LEASE_HARD_TERMINATE_AFTER, KEY_LEASE_RENEW_AFTER, KEY_LEASE_SOFT_TERMINATE_AFTER, - }, - subscribe::Subscription, - PlaneDatabase, - }, +use axum::{ + extract::{ws::WebSocket, ConnectInfo, Path, Query, State, WebSocketUpgrade}, + http::StatusCode, + response::{IntoResponse, Response}, +}; +use plane_common::{ log_types::LoggableTime, protocol::{ - BackendAction, Heartbeat, KeyDeadlines, MessageFromDrone, MessageToDrone, RenewKeyResponse, + ApiErrorKind, BackendAction, BackendActionMessage, Heartbeat, KeyDeadlines, + MessageFromDrone, MessageToDrone, RenewKeyResponse, }, typed_socket::{server::new_server, TypedSocket}, types::{ backend_state::TerminationReason, ClusterName, DronePoolName, NodeId, TerminationKind, }, }; -use axum::{ - extract::{ws::WebSocket, ConnectInfo, Path, Query, State, WebSocketUpgrade}, - http::StatusCode, - response::{IntoResponse, Response}, -}; use serde::Deserialize; use std::{ net::{IpAddr, SocketAddr}, @@ -30,6 +21,16 @@ use std::{ }; use valuable::Valuable; +use crate::database::{ + backend_key::{ + KEY_LEASE_HARD_TERMINATE_AFTER, KEY_LEASE_RENEW_AFTER, KEY_LEASE_SOFT_TERMINATE_AFTER, + }, + subscribe::Subscription, + PlaneDatabase, +}; + +use super::{core::Controller, error::IntoApiError}; + #[derive(Deserialize)] pub struct DroneSocketQuery { pool: Option, diff --git a/plane/src/controller/error.rs b/plane/src/controller/error.rs index bef7a9a48..970efd157 100644 --- a/plane/src/controller/error.rs +++ b/plane/src/controller/error.rs @@ -1,42 +1,13 @@ -use crate::util::random_string; use axum::{ http::StatusCode, response::{IntoResponse, Response}, Json, }; -use serde::{Deserialize, Serialize}; -use std::{ - error::Error, - fmt::{Debug, Display}, +use plane_common::{ + protocol::{ApiError, ApiErrorKind}, + util::random_string, }; - -#[derive(Serialize, Deserialize, Debug, Clone, Copy)] -pub enum ApiErrorKind { - FailedToAcquireKey, - KeyUnheldNoSpawnConfig, - KeyHeldUnhealthy, - KeyHeld, - NoDroneAvailable, - FailedToRemoveKey, - DatabaseError, - NoClusterProvided, - NotFound, - InvalidClusterName, - Other, -} - -#[derive(thiserror::Error, Debug, Serialize, Deserialize)] -pub struct ApiError { - pub id: String, - pub kind: ApiErrorKind, - pub message: String, -} - -impl Display for ApiError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self) - } -} +use std::{error::Error, fmt::Debug}; pub fn err_to_response( error: E, diff --git a/plane/src/controller/mod.rs b/plane/src/controller/mod.rs index aafc01073..c96adb5ea 100644 --- a/plane/src/controller/mod.rs +++ b/plane/src/controller/mod.rs @@ -9,15 +9,11 @@ use self::{ }; use crate::{ cleanup, - client::PlaneClient, controller::{connect::handle_connect, core::Controller, drone::handle_drone_socket}, database::{connect_and_migrate, PlaneDatabase}, heartbeat_consts::HEARTBEAT_INTERVAL, - names::ControllerName, signals::wait_for_shutdown_signal, - types::ClusterName, util::GuardHandle, - PLANE_GIT_HASH, PLANE_VERSION, }; use anyhow::{Context, Result}; use axum::{ @@ -29,6 +25,13 @@ use axum::{ }; use forward_auth::forward_layer; use futures_util::never::Never; +use plane_common::{ + names::ControllerName, + protocol::StatusResponse, + types::ClusterName, + version::{PLANE_GIT_HASH, PLANE_VERSION}, + PlaneClient, +}; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; use std::net::SocketAddr; @@ -63,13 +66,6 @@ mod terminate; /// will continue blocking indefinitely, which is why we need a timeout. const TERMINATE_TIMEOUT_DURATION: std::time::Duration = std::time::Duration::from_secs(2); -#[derive(Serialize, Deserialize, Debug)] -pub struct StatusResponse { - pub status: String, - pub version: String, - pub hash: String, -} - pub async fn status( State(controller): State, ) -> Result, Response> { diff --git a/plane/src/controller/proxy.rs b/plane/src/controller/proxy.rs index 26c4e4618..b6e604796 100644 --- a/plane/src/controller/proxy.rs +++ b/plane/src/controller/proxy.rs @@ -1,23 +1,22 @@ -use super::{error::ApiErrorKind, Controller}; -use crate::{ - controller::error::IntoApiError, - database::{ - backend::RouteInfoResult, - subscribe::{Notification, Subscription}, - }, +use super::{core::Controller, error::IntoApiError}; +use crate::database::{ + backend::RouteInfoResult, + subscribe::{Notification, Subscription}, +}; +use axum::{ + extract::{ws::WebSocket, ConnectInfo, Path, State, WebSocketUpgrade}, + http::StatusCode, + response::{IntoResponse, Response}, +}; +use plane_common::{ names::{BackendName, Name}, protocol::{ - CertManagerRequest, CertManagerResponse, MessageFromProxy, MessageToProxy, + ApiErrorKind, CertManagerRequest, CertManagerResponse, MessageFromProxy, MessageToProxy, RouteInfoRequest, RouteInfoResponse, }, typed_socket::{server::new_server, TypedSocket}, types::{BackendState, BearerToken, ClusterName, NodeId}, }; -use axum::{ - extract::{ws::WebSocket, ConnectInfo, Path, State, WebSocketUpgrade}, - http::StatusCode, - response::{IntoResponse, Response}, -}; use std::net::{IpAddr, SocketAddr}; use tokio::select; use valuable::Valuable; diff --git a/plane/src/controller/terminate.rs b/plane/src/controller/terminate.rs index 2c6f04343..c3002e9e2 100644 --- a/plane/src/controller/terminate.rs +++ b/plane/src/controller/terminate.rs @@ -1,14 +1,14 @@ use super::{core::Controller, error::IntoApiError}; -use crate::{ - names::BackendName, - protocol::BackendAction, - types::{backend_state::TerminationReason, TerminationKind}, -}; use axum::{ extract::{Path, State}, response::Response, Json, }; +use plane_common::{ + names::BackendName, + protocol::BackendAction, + types::{TerminationKind, TerminationReason}, +}; async fn terminate( controller: &Controller, diff --git a/plane/src/database/acme.rs b/plane/src/database/acme.rs index e000ddc7f..9c623c82c 100644 --- a/plane/src/database/acme.rs +++ b/plane/src/database/acme.rs @@ -1,4 +1,4 @@ -use crate::types::{ClusterName, NodeId}; +use plane_common::types::{ClusterName, NodeId}; use sqlx::query; use sqlx::PgPool; diff --git a/plane/src/database/backend.rs b/plane/src/database/backend.rs index da9839b48..a65860236 100644 --- a/plane/src/database/backend.rs +++ b/plane/src/database/backend.rs @@ -2,18 +2,17 @@ use super::{ subscribe::{emit_backend_metrics, emit_with_key}, PlaneDatabase, }; -use crate::{ +use chrono::{DateTime, Utc}; +use futures_util::Stream; +use plane_common::{ log_types::BackendAddr, - names::{BackendActionName, BackendName, DroneName}, - protocol::{BackendAction, RouteInfo}, + names::{BackendName, DroneName}, + protocol::{BackendActionMessage, BackendMetricsMessage, RouteInfo}, types::{ backend_state::BackendStatusStreamEntry, BackendState, BackendStatus, BearerToken, ClusterName, NodeId, SecretToken, Subdomain, }, }; -use chrono::{DateTime, Utc}; -use futures_util::Stream; -use serde::{Deserialize, Serialize}; use sqlx::PgConnection; use std::{fmt::Debug, net::SocketAddr, str::FromStr}; use valuable::Valuable; @@ -22,43 +21,12 @@ pub struct BackendDatabase<'a> { db: &'a PlaneDatabase, } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct BackendActionMessage { - pub action_id: BackendActionName, - pub backend_id: BackendName, - pub drone_id: NodeId, - pub action: BackendAction, -} - impl super::subscribe::NotificationPayload for BackendActionMessage { fn kind() -> &'static str { "backend_action" } } -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct BackendMetricsMessage { - pub backend_id: BackendName, - /// Memory used by backend excluding inactive file cache, same as use shown by docker stats - /// ref: https://github.com/docker/cli/blob/master/cli/command/container/stats_helpers.go#L227C45-L227C45 - pub mem_used: u64, - /// Memory used by backend in bytes - /// (calculated using kernel memory used by cgroup + page cache memory used by cgroup) - pub mem_total: u64, - /// Active memory (non reclaimable) - pub mem_active: u64, - /// Inactive memory (reclaimable) - pub mem_inactive: u64, - /// Unevictable memory (mlock etc) - pub mem_unevictable: u64, - /// The backend's memory limit - pub mem_limit: u64, - /// Nanoseconds of CPU used by backend since last message - pub cpu_used: u64, - /// Total CPU nanoseconds for system since last message - pub sys_cpu: u64, -} - impl super::subscribe::NotificationPayload for BackendMetricsMessage { fn kind() -> &'static str { "backend_metrics" diff --git a/plane/src/database/backend_actions.rs b/plane/src/database/backend_actions.rs index 44dfb4561..5f7778aaa 100644 --- a/plane/src/database/backend_actions.rs +++ b/plane/src/database/backend_actions.rs @@ -1,7 +1,7 @@ -use super::{backend::BackendActionMessage, connect::ConnectError, subscribe::emit_with_key}; -use crate::{ +use super::{connect::ConnectError, subscribe::emit_with_key}; +use plane_common::{ names::{BackendActionName, BackendName, Name}, - protocol::BackendAction, + protocol::{BackendAction, BackendActionMessage}, types::NodeId, }; use sqlx::{PgPool, Postgres}; diff --git a/plane/src/database/backend_key.rs b/plane/src/database/backend_key.rs index 50f9ecc4a..6cc64b5f2 100644 --- a/plane/src/database/backend_key.rs +++ b/plane/src/database/backend_key.rs @@ -7,11 +7,11 @@ //! assert!(KEY_LEASE_EXPIRATION > KEY_LEASE_HARD_TERMINATE_AFTER); //! ``` -use crate::{ +use chrono::{DateTime, Utc}; +use plane_common::{ names::BackendName, types::{BackendStatus, BearerToken, ClusterName, KeyConfig, Subdomain}, }; -use chrono::{DateTime, Utc}; use sqlx::{postgres::types::PgInterval, PgPool}; use std::{str::FromStr, time::Duration}; diff --git a/plane/src/database/cluster.rs b/plane/src/database/cluster.rs index a9e1b5604..45c187178 100644 --- a/plane/src/database/cluster.rs +++ b/plane/src/database/cluster.rs @@ -1,4 +1,4 @@ -use crate::{ +use plane_common::{ names::{AnyNodeName, ControllerName}, types::{BackendStatus, ClusterName, ClusterState, DroneState, NodeState}, }; diff --git a/plane/src/database/connect.rs b/plane/src/database/connect.rs index c605d9d31..849ffffc6 100644 --- a/plane/src/database/connect.rs +++ b/plane/src/database/connect.rs @@ -1,15 +1,15 @@ +use crate::database::{ + backend_key::{KeysDatabase, KEY_LEASE_EXPIRATION}, + drone::DroneDatabase, +}; + use super::{ backend::emit_state_change, backend_actions::create_pending_action, backend_key::{KEY_LEASE_RENEW_AFTER, KEY_LEASE_SOFT_TERMINATE_AFTER}, drone::DroneForSpawn, }; -use crate::{ - client::PlaneClient, - database::{ - backend_key::{KeysDatabase, KEY_LEASE_EXPIRATION}, - drone::DroneDatabase, - }, +use plane_common::{ log_types::LoggableTime, names::{BackendName, OrRandom}, protocol::{AcquiredKey, BackendAction, KeyDeadlines}, @@ -18,6 +18,7 @@ use crate::{ KeyConfig, RevokeRequest, SecretToken, SpawnConfig, }, util::random_token, + PlaneClient, }; use serde_json::{Map, Value}; use sqlx::{postgres::types::PgInterval, PgPool}; diff --git a/plane/src/database/controller.rs b/plane/src/database/controller.rs index 7b8d7731c..234adcdc1 100644 --- a/plane/src/database/controller.rs +++ b/plane/src/database/controller.rs @@ -1,9 +1,9 @@ -use crate::names::ControllerName; use crate::PLANE_GIT_HASH; use crate::PLANE_VERSION; use anyhow::Result; use chrono::DateTime; use chrono::Utc; +use plane_common::names::ControllerName; use sqlx::PgPool; pub struct ControllerDatabase<'a> { diff --git a/plane/src/database/drone.rs b/plane/src/database/drone.rs index a66ec8cfe..851470592 100644 --- a/plane/src/database/drone.rs +++ b/plane/src/database/drone.rs @@ -1,13 +1,12 @@ -use crate::{ - heartbeat_consts::UNHEALTHY_SECONDS, - names::{ControllerName, DroneName}, - types::{BackendStatus, ClusterName, DronePoolName, NodeId}, -}; use chrono::{DateTime, Utc}; +use plane_common::names::{ControllerName, DroneName}; +use plane_common::types::{BackendStatus, ClusterName, DronePoolName, NodeId}; use sqlx::{postgres::types::PgInterval, query, PgPool}; use std::str::FromStr; use std::time::Duration; +use crate::heartbeat_consts::UNHEALTHY_SECONDS; + pub struct DroneDatabase<'a> { pool: &'a PgPool, } diff --git a/plane/src/database/mod.rs b/plane/src/database/mod.rs index 9e2734534..54bfb2bb2 100644 --- a/plane/src/database/mod.rs +++ b/plane/src/database/mod.rs @@ -10,9 +10,9 @@ use self::{ node::NodeDatabase, subscribe::{EventSubscriptionManager, Notification, NotificationPayload, Subscription}, }; -use crate::{ - client::PlaneClient, +use plane_common::{ types::{ClusterName, ConnectRequest, ConnectResponse, RevokeRequest}, + PlaneClient, }; use serde_json::Value; use sqlx::{postgres::PgPoolOptions, PgPool}; diff --git a/plane/src/database/node.rs b/plane/src/database/node.rs index b5561f614..40ab4bba9 100644 --- a/plane/src/database/node.rs +++ b/plane/src/database/node.rs @@ -3,13 +3,13 @@ use super::{ util::MapSqlxError, }; use crate::heartbeat_consts::UNHEALTHY_SECONDS; -use crate::{ +use anyhow::Result; +use chrono::{DateTime, Utc}; +use plane_common::{ names::{AnyNodeName, ControllerName, NodeName}, types::{ClusterName, NodeId, NodeKind}, - PlaneVersionInfo, + version::PlaneVersionInfo, }; -use anyhow::Result; -use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::{postgres::types::PgInterval, query, types::ipnetwork::IpNetwork, PgPool}; use std::{net::IpAddr, time::Duration}; diff --git a/plane/src/database/subscribe.rs b/plane/src/database/subscribe.rs index bda2c48ce..7a78eaf80 100644 --- a/plane/src/database/subscribe.rs +++ b/plane/src/database/subscribe.rs @@ -1,6 +1,5 @@ -use crate::database::{backend::BackendMetricsMessage, util::MapSqlxError}; -use crate::util::ExponentialBackoff; use chrono::{DateTime, Utc}; +use plane_common::{exponential_backoff::ExponentialBackoff, protocol::BackendMetricsMessage}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_json::Value; use sqlx::{postgres::PgListener, PgConnection, PgPool}; @@ -15,6 +14,8 @@ use tokio::{ task::JoinHandle, }; +use crate::database::util::MapSqlxError; + type ListenerMap = Arc), Box>>>; pub const EVENT_CHANNEL: &str = "plane_events"; diff --git a/plane/src/dns/command.rs b/plane/src/dns/command.rs index 7ccb0f9ed..0ff106362 100644 --- a/plane/src/dns/command.rs +++ b/plane/src/dns/command.rs @@ -1,5 +1,5 @@ -use crate::names::{AcmeDnsServerName, OrRandom}; use clap::Parser; +use plane_common::names::{AcmeDnsServerName, OrRandom}; use url::Url; #[derive(Parser)] diff --git a/plane/src/dns/mod.rs b/plane/src/dns/mod.rs index b85f22992..f90b0362a 100644 --- a/plane/src/dns/mod.rs +++ b/plane/src/dns/mod.rs @@ -1,15 +1,16 @@ +use crate::signals::wait_for_shutdown_signal; + use self::{error::Result, name_to_cluster::NameToCluster}; -use crate::{ - client::PlaneClient, - dns::error::OrDnsError, +use anyhow::anyhow; +use dashmap::DashMap; +use error::OrDnsError; +use plane_common::{ names::AcmeDnsServerName, protocol::{MessageFromDns, MessageToDns}, - signals::wait_for_shutdown_signal, typed_socket::client::TypedSocketConnector, types::ClusterName, + PlaneClient, }; -use anyhow::anyhow; -use dashmap::DashMap; use serde::{Deserialize, Serialize}; use std::{net::Ipv4Addr, sync::Arc, time::Duration}; use tokio::{ diff --git a/plane/src/dns/name_to_cluster.rs b/plane/src/dns/name_to_cluster.rs index bce2a1879..1e07ca6d5 100644 --- a/plane/src/dns/name_to_cluster.rs +++ b/plane/src/dns/name_to_cluster.rs @@ -1,7 +1,6 @@ +use plane_common::types::ClusterName; use std::str::FromStr; -use crate::types::ClusterName; - /// Maps a requested domain name to a cluster name. /// /// This can be configured to operate in two ways. @@ -47,7 +46,7 @@ impl NameToCluster { #[cfg(test)] mod test { - use crate::types::ClusterName; + use plane_common::types::ClusterName; use std::str::FromStr; #[test] diff --git a/plane/src/drone/backend_manager.rs b/plane/src/drone/backend_manager.rs index 0e5cef228..0ee1f952e 100644 --- a/plane/src/drone/backend_manager.rs +++ b/plane/src/drone/backend_manager.rs @@ -1,15 +1,15 @@ -use crate::drone::runtime::Runtime; -use crate::{ +use crate::{drone::runtime::Runtime, util::GuardHandle}; +use anyhow::Result; +use futures_util::Future; +use plane_common::{ + exponential_backoff::ExponentialBackoff, names::BackendName, protocol::AcquiredKey, types::{ backend_state::{BackendError, TerminationReason}, BackendState, BearerToken, TerminationKind, }, - util::{ExponentialBackoff, GuardHandle}, }; -use anyhow::Result; -use futures_util::Future; use std::{error::Error, fmt::Debug}; use std::{future::pending, pin::Pin}; use std::{ diff --git a/plane/src/drone/command.rs b/plane/src/drone/command.rs index a03f59a96..a0eed2237 100644 --- a/plane/src/drone/command.rs +++ b/plane/src/drone/command.rs @@ -1,13 +1,15 @@ -use super::{runtime::unix_socket::UnixSocketRuntimeConfig, ExecutorConfig}; -use crate::{ - drone::{runtime::docker::DockerRuntimeConfig, DroneConfig}, - names::{DroneName, OrRandom}, - types::{ClusterName, DronePoolName}, - util::resolve_hostname, +use super::{ + runtime::{docker::DockerRuntimeConfig, unix_socket::UnixSocketRuntimeConfig}, + DroneConfig, ExecutorConfig, }; +use crate::util::resolve_hostname; use anyhow::Result; use chrono::Duration; use clap::Parser; +use plane_common::{ + names::{DroneName, OrRandom}, + types::{ClusterName, DronePoolName}, +}; use std::{net::IpAddr, path::PathBuf}; use url::Url; diff --git a/plane/src/drone/executor.rs b/plane/src/drone/executor.rs index 63ce3de74..0b14d9945 100644 --- a/plane/src/drone/executor.rs +++ b/plane/src/drone/executor.rs @@ -1,15 +1,15 @@ -use super::{backend_manager::BackendManager, state_store::StateStore}; -use crate::{ - drone::runtime::Runtime, - names::BackendName, - protocol::{BackendAction, BackendEventId, BackendStateMessage}, - types::{BackendState, BackendStatus, TerminationReason}, - util::{ExponentialBackoff, GuardHandle}, -}; +use super::{backend_manager::BackendManager, runtime::Runtime, state_store::StateStore}; +use crate::util::GuardHandle; use anyhow::Result; use chrono::Utc; use dashmap::DashMap; use futures_util::{future::join_all, StreamExt}; +use plane_common::{ + exponential_backoff::ExponentialBackoff, + names::BackendName, + protocol::{BackendAction, BackendEventId, BackendStateMessage}, + types::{BackendState, BackendStatus, TerminationReason}, +}; use std::{ net::IpAddr, sync::{Arc, Mutex}, diff --git a/plane/src/drone/heartbeat.rs b/plane/src/drone/heartbeat.rs index eb7d10199..54d52c24c 100644 --- a/plane/src/drone/heartbeat.rs +++ b/plane/src/drone/heartbeat.rs @@ -1,8 +1,6 @@ -use crate::{ - heartbeat_consts::HEARTBEAT_INTERVAL, log_types::LoggableTime, protocol::Heartbeat, - typed_socket::TypedSocketSender, -}; +use crate::heartbeat_consts::HEARTBEAT_INTERVAL; use chrono::Utc; +use plane_common::{log_types::LoggableTime, protocol::Heartbeat, typed_socket::TypedSocketSender}; use tokio::task::JoinHandle; /// A background task that sends heartbeats to the server. diff --git a/plane/src/drone/key_manager.rs b/plane/src/drone/key_manager.rs index d2e66b5b3..cc79bdd5d 100644 --- a/plane/src/drone/key_manager.rs +++ b/plane/src/drone/key_manager.rs @@ -1,13 +1,13 @@ use super::executor::Executor; -use crate::{ +use crate::util::GuardHandle; +use chrono::Utc; +use plane_common::{ log_types::LoggableTime, names::BackendName, protocol::{AcquiredKey, BackendAction, KeyDeadlines, RenewKeyRequest}, typed_socket::TypedSocketSender, types::{backend_state::TerminationReason, TerminationKind}, - util::GuardHandle, }; -use chrono::Utc; use std::{collections::HashMap, sync::Arc, time::Duration}; use tokio::time::sleep; use valuable::Valuable; diff --git a/plane/src/drone/mod.rs b/plane/src/drone/mod.rs index 639e44ba1..faad80874 100644 --- a/plane/src/drone/mod.rs +++ b/plane/src/drone/mod.rs @@ -9,18 +9,19 @@ use self::{ }, state_store::StateStore, }; -use crate::{ - client::PlaneClient, - database::backend::BackendActionMessage, - drone::runtime::docker::DockerRuntime, +use crate::signals::wait_for_shutdown_signal; +use anyhow::{anyhow, Result}; +use chrono::{Duration, Utc}; +use plane_common::{ names::DroneName, - protocol::{BackendAction, MessageFromDrone, MessageToDrone, RenewKeyResponse}, - signals::wait_for_shutdown_signal, + protocol::{ + BackendAction, BackendActionMessage, MessageFromDrone, MessageToDrone, RenewKeyResponse, + }, typed_socket::{client::TypedSocketConnector, TypedSocketSender}, types::{BackendState, ClusterName, DronePoolName}, + PlaneClient, }; -use anyhow::{anyhow, Result}; -use chrono::{Duration, Utc}; +use runtime::docker::DockerRuntime; use rusqlite::Connection; use serde::{Deserialize, Serialize}; use std::{ @@ -289,7 +290,7 @@ pub struct DroneConfig { note = "Moved to `executor_config` (only applies to DockerRuntimeConfig)." )] pub auto_prune: Option, - #[serde(with = "crate::serialization::serialize_optional_duration_as_seconds")] + #[serde(with = "plane_common::serialization::serialize_optional_duration_as_seconds")] #[deprecated( since = "0.4.12", note = "Moved to `executor_config` (only applies to DockerRuntimeConfig)." diff --git a/plane/src/drone/runtime/docker/commands.rs b/plane/src/drone/runtime/docker/commands.rs index 665d1c26a..0af5e26bd 100644 --- a/plane/src/drone/runtime/docker/commands.rs +++ b/plane/src/drone/runtime/docker/commands.rs @@ -1,9 +1,4 @@ use super::{types::ContainerId, DockerRuntime}; -use crate::{ - names::BackendName, - protocol::AcquiredKey, - types::{BearerToken, DockerExecutorConfig, Mount}, -}; use anyhow::Result; use bollard::{ auth::DockerCredentials, @@ -11,6 +6,11 @@ use bollard::{ Docker, }; use futures_util::StreamExt; +use plane_common::{ + names::BackendName, + protocol::AcquiredKey, + types::{BearerToken, DockerExecutorConfig, Mount}, +}; use std::{ collections::HashMap, path::{Component, Path, PathBuf}, @@ -294,7 +294,7 @@ pub async fn run_container( #[cfg(test)] mod tests { use super::*; - use crate::{ + use plane_common::{ log_types::LoggableTime, names::Name, protocol::{AcquiredKey, KeyDeadlines}, diff --git a/plane/src/drone/runtime/docker/metrics.rs b/plane/src/drone/runtime/docker/metrics.rs index 44131fb2f..549b1877b 100644 --- a/plane/src/drone/runtime/docker/metrics.rs +++ b/plane/src/drone/runtime/docker/metrics.rs @@ -1,7 +1,7 @@ use super::{types::ContainerId, MetricsCallback}; -use crate::{database::backend::BackendMetricsMessage, names::BackendName}; use bollard::{container::StatsOptions, Docker}; use futures_util::Stream; +use plane_common::{names::BackendName, protocol::BackendMetricsMessage}; use std::sync::{Arc, Mutex}; use tokio::time::{Duration, Instant}; use tokio_stream::StreamExt; diff --git a/plane/src/drone/runtime/docker/mod.rs b/plane/src/drone/runtime/docker/mod.rs index bfe429e39..83fbbe651 100644 --- a/plane/src/drone/runtime/docker/mod.rs +++ b/plane/src/drone/runtime/docker/mod.rs @@ -4,12 +4,8 @@ use self::{ wait_backend::wait_for_backend, }; use crate::{ - database::backend::BackendMetricsMessage, drone::runtime::{docker::metrics::metrics_loop, Runtime}, heartbeat_consts::KILL_AFTER_SOFT_TERMINATE_SECONDS, - names::BackendName, - protocol::AcquiredKey, - types::{backend_state::BackendError, BearerToken, DockerExecutorConfig, PullPolicy}, util::GuardHandle, }; use anyhow::Result; @@ -21,6 +17,11 @@ use bollard::{ Docker, }; use chrono::{DateTime, Duration, Utc}; +use plane_common::{ + names::BackendName, + protocol::{AcquiredKey, BackendMetricsMessage}, + types::{backend_state::BackendError, BearerToken, DockerExecutorConfig, PullPolicy}, +}; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, path::PathBuf, pin::Pin}; use std::{ @@ -53,7 +54,7 @@ pub struct DockerRuntimeConfig { pub auto_prune: Option, #[serde(default)] // Necessary because we use a custom deserializer; see https://stackoverflow.com/a/44303505 - #[serde(with = "crate::serialization::serialize_optional_duration_as_seconds")] + #[serde(with = "plane_common::serialization::serialize_optional_duration_as_seconds")] pub cleanup_min_age: Option, } diff --git a/plane/src/drone/runtime/docker/types.rs b/plane/src/drone/runtime/docker/types.rs index eb2a563ad..8b7a16ecc 100644 --- a/plane/src/drone/runtime/docker/types.rs +++ b/plane/src/drone/runtime/docker/types.rs @@ -1,4 +1,4 @@ -use crate::names::BackendName; +use plane_common::names::{BackendName, NameError}; use serde::{Deserialize, Serialize}; use std::fmt::Display; @@ -13,7 +13,7 @@ impl From for ContainerId { impl From<&BackendName> for ContainerId { fn from(backend_id: &BackendName) -> Self { - Self(format!("plane-{}", backend_id)) + ContainerId(backend_id.to_container_id()) } } @@ -28,10 +28,19 @@ impl Display for ContainerId { write!(f, "{}", &self.0) } } + +impl TryFrom for BackendName { + type Error = NameError; + + fn try_from(container_id: ContainerId) -> Result { + BackendName::from_container_id(container_id.0) + } +} + #[cfg(test)] mod tests { - use super::*; - use crate::names::{BackendName, Name}; + use crate::drone::runtime::docker::types::ContainerId; + use plane_common::names::{BackendName, Name}; #[test] fn test_backend_name_container_id_roundtrip() { diff --git a/plane/src/drone/runtime/docker/wait_backend.rs b/plane/src/drone/runtime/docker/wait_backend.rs index 8799f9f46..72becacee 100644 --- a/plane/src/drone/runtime/docker/wait_backend.rs +++ b/plane/src/drone/runtime/docker/wait_backend.rs @@ -1,4 +1,4 @@ -use crate::types::backend_state::BackendError; +use plane_common::types::backend_state::BackendError; use std::{ net::SocketAddr, time::{Duration, Instant}, diff --git a/plane/src/drone/runtime/mod.rs b/plane/src/drone/runtime/mod.rs index 97a79ee65..e595980b7 100644 --- a/plane/src/drone/runtime/mod.rs +++ b/plane/src/drone/runtime/mod.rs @@ -1,12 +1,11 @@ -use crate::{ - database::backend::BackendMetricsMessage, - names::BackendName, - protocol::AcquiredKey, - types::{backend_state::BackendError, BearerToken}, -}; use anyhow::Error; use docker::{SpawnResult, TerminateEvent}; use futures_util::Stream; +use plane_common::{ + names::BackendName, + protocol::{AcquiredKey, BackendMetricsMessage}, + types::{backend_state::BackendError, BearerToken}, +}; use std::{net::SocketAddr, pin::Pin}; pub mod docker; diff --git a/plane/src/drone/runtime/unix_socket/mod.rs b/plane/src/drone/runtime/unix_socket/mod.rs index f1a1b9b02..f7e3c1f75 100644 --- a/plane/src/drone/runtime/unix_socket/mod.rs +++ b/plane/src/drone/runtime/unix_socket/mod.rs @@ -1,15 +1,15 @@ +use crate::typed_unix_socket::client::TypedUnixSocketClient; + use super::{ docker::{SpawnResult, TerminateEvent}, Runtime, }; -use crate::{ - database::backend::BackendMetricsMessage, +use anyhow::{Error, Result}; +use plane_common::{ names::BackendName, - protocol::AcquiredKey, - typed_unix_socket::client::TypedUnixSocketClient, + protocol::{AcquiredKey, BackendMetricsMessage}, types::{backend_state::BackendError, BearerToken, DockerExecutorConfig}, }; -use anyhow::{Error, Result}; use serde::{Deserialize, Serialize}; use std::{net::SocketAddr, path::PathBuf, pin::Pin}; use tokio_stream::{Stream, StreamExt}; diff --git a/plane/src/drone/state_store.rs b/plane/src/drone/state_store.rs index 3ea7b8583..da04d473c 100644 --- a/plane/src/drone/state_store.rs +++ b/plane/src/drone/state_store.rs @@ -1,11 +1,11 @@ -use crate::{ +use anyhow::Result; +use chrono::{DateTime, Utc}; +use plane_common::{ log_types::LoggableTime, names::BackendName, protocol::{BackendEventId, BackendStateMessage}, types::BackendState, }; -use anyhow::Result; -use chrono::{DateTime, Utc}; use rusqlite::Connection; /// An array of sqlite commands used to initialize the state store. @@ -231,7 +231,7 @@ impl StateStore { #[cfg(test)] mod test { use super::*; - use crate::{ + use plane_common::{ log_types::BackendAddr, names::Name, types::{BackendStatus, TerminationReason}, diff --git a/plane/src/lib.rs b/plane/src/lib.rs index cae70e910..ea8c5643e 100644 --- a/plane/src/lib.rs +++ b/plane/src/lib.rs @@ -5,50 +5,23 @@ use controller::ControllerConfig; use dns::DnsConfig; use drone::DroneConfig; +use plane_common::version::{PLANE_GIT_HASH, PLANE_VERSION}; use proxy::ProxyConfig; use serde::{Deserialize, Serialize}; pub mod admin; pub mod cleanup; -pub mod client; pub mod controller; pub mod database; pub mod dns; pub mod drone; pub mod heartbeat_consts; pub mod init_tracing; -pub mod log_types; -pub mod names; -pub mod protocol; pub mod proxy; -pub mod serialization; pub mod signals; -pub mod typed_socket; pub mod typed_unix_socket; -pub mod types; pub mod util; -/// The version of the plane binary from Cargo.toml. -pub const PLANE_VERSION: &str = env!("CARGO_PKG_VERSION"); - -/// The git hash of the plane binary (passed from build.rs) -pub const PLANE_GIT_HASH: &str = env!("GIT_HASH"); - -pub const SERVER_NAME: &str = concat!("Plane/", env!("CARGO_PKG_VERSION"), "-", env!("GIT_HASH")); - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] -pub struct PlaneVersionInfo { - pub version: String, - pub git_hash: String, -} - -pub fn plane_version_info() -> PlaneVersionInfo { - PlaneVersionInfo { - version: PLANE_VERSION.to_string(), - git_hash: PLANE_GIT_HASH.to_string(), - } -} - #[derive(Debug, Clone, Serialize, Deserialize)] pub enum Plan { Controller(ControllerConfig), diff --git a/plane/src/main.rs b/plane/src/main.rs index 1ba42bc5a..f44e44727 100644 --- a/plane/src/main.rs +++ b/plane/src/main.rs @@ -15,7 +15,8 @@ use plane::drone::run_drone; use plane::init_tracing::init_tracing; use plane::proxy::command::ProxyOpts; use plane::proxy::run_proxy; -use plane::{Plan, PLANE_GIT_HASH, PLANE_VERSION}; +use plane::Plan; +use plane_common::version::{PLANE_GIT_HASH, PLANE_VERSION}; use std::ffi::OsStr; use std::path::PathBuf; diff --git a/plane/src/proxy/cert_manager.rs b/plane/src/proxy/cert_manager.rs index 48cb2b564..136a84970 100644 --- a/plane/src/proxy/cert_manager.rs +++ b/plane/src/proxy/cert_manager.rs @@ -1,15 +1,15 @@ use super::{cert_pair::CertificatePair, AcmeConfig}; -use crate::{ - log_types::LoggableTime, - protocol::{CertManagerRequest, CertManagerResponse}, - types::ClusterName, -}; use acme2_eab::{ gen_rsa_private_key, Account, AccountBuilder, AuthorizationStatus, ChallengeStatus, Csr, DirectoryBuilder, OrderBuilder, OrderStatus, }; use anyhow::{anyhow, Context, Result}; use chrono::Utc; +use plane_common::{ + log_types::LoggableTime, + protocol::{CertManagerRequest, CertManagerResponse}, + types::ClusterName, +}; use plane_dynamic_proxy::tokio_rustls::rustls::{ server::{ClientHello, ResolvesServerCert}, sign::CertifiedKey, diff --git a/plane/src/proxy/cert_pair.rs b/plane/src/proxy/cert_pair.rs index 5ecaafce0..7dee31f5f 100644 --- a/plane/src/proxy/cert_pair.rs +++ b/plane/src/proxy/cert_pair.rs @@ -1,13 +1,16 @@ -use crate::log_types::LoggableTime; use anyhow::{anyhow, Result}; +use chrono::{DateTime, Utc}; use pem::Pem; +use plane_common::log_types::LoggableTime; use plane_dynamic_proxy::rustls::{ crypto::aws_lc_rs::sign::any_supported_type, pki_types::PrivateKeyDer, }; use plane_dynamic_proxy::tokio_rustls::rustls::sign::CertifiedKey; use rustls_pki_types::CertificateDer; use serde::{Deserialize, Serialize}; +use std::time::SystemTime; use std::{fs::Permissions, io, os::unix::fs::PermissionsExt, path::Path}; +use time::OffsetDateTime; use x509_parser::{certificate::X509Certificate, oid_registry::asn1_rs::FromDer}; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -47,6 +50,12 @@ pub struct CertificatePair { pub validity_end: LoggableTime, } +fn convert_time(time: OffsetDateTime) -> LoggableTime { + let t: SystemTime = time.into(); + let t: DateTime = t.into(); + LoggableTime(t) +} + impl CertificatePair { fn new(key: &PrivateKeyDer, certs: Vec) -> Result { let private_key_der = key.secret_der().to_vec(); @@ -83,8 +92,8 @@ impl CertificatePair { certified_key, common_name, private_key_der, - validity_start: validity_start.into(), - validity_end: validity_end.into(), + validity_start: convert_time(validity_start), + validity_end: convert_time(validity_end), }) } diff --git a/plane/src/proxy/command.rs b/plane/src/proxy/command.rs index da7b842bd..0f6f5b74c 100644 --- a/plane/src/proxy/command.rs +++ b/plane/src/proxy/command.rs @@ -1,14 +1,13 @@ -use crate::{ +use anyhow::{anyhow, Result}; +use clap::Parser; +use plane_common::{ names::{OrRandom, ProxyName}, - proxy::{AcmeConfig, AcmeEabConfiguration, ServerPortConfig}, types::ClusterName, }; -use anyhow::{anyhow, Result}; -use clap::Parser; use std::path::PathBuf; use url::Url; -use super::ProxyConfig; +use super::{AcmeConfig, AcmeEabConfiguration, ProxyConfig, ServerPortConfig}; const LOCAL_HTTP_PORT: u16 = 9090; const PROD_HTTP_PORT: u16 = 80; diff --git a/plane/src/proxy/connection_monitor.rs b/plane/src/proxy/connection_monitor.rs index 83ca54769..9527b0dfa 100644 --- a/plane/src/proxy/connection_monitor.rs +++ b/plane/src/proxy/connection_monitor.rs @@ -1,4 +1,5 @@ -use crate::{heartbeat_consts::HEARTBEAT_INTERVAL, names::BackendName}; +use crate::heartbeat_consts::HEARTBEAT_INTERVAL; +use plane_common::names::BackendName; use std::{ collections::{hash_map::Entry, HashMap, VecDeque}, sync::{Arc, Mutex}, diff --git a/plane/src/proxy/mod.rs b/plane/src/proxy/mod.rs index 377a0a233..113ea5f0f 100644 --- a/plane/src/proxy/mod.rs +++ b/plane/src/proxy/mod.rs @@ -1,8 +1,10 @@ use self::proxy_connection::ProxyConnection; -use crate::names::ProxyName; use crate::proxy::cert_manager::watcher_manager_pair; -use crate::{client::PlaneClient, signals::wait_for_shutdown_signal, types::ClusterName}; +use crate::signals::wait_for_shutdown_signal; use anyhow::Result; +use plane_common::names::ProxyName; +use plane_common::types::ClusterName; +use plane_common::PlaneClient; use plane_dynamic_proxy::server::{ ServerWithHttpRedirect, ServerWithHttpRedirectConfig, ServerWithHttpRedirectHttpsConfig, }; diff --git a/plane/src/proxy/proxy_connection.rs b/plane/src/proxy/proxy_connection.rs index 4ad653469..b8bb2e20f 100644 --- a/plane/src/proxy/proxy_connection.rs +++ b/plane/src/proxy/proxy_connection.rs @@ -1,9 +1,9 @@ use super::{cert_manager::CertManager, proxy_server::ProxyState}; -use crate::{ - client::PlaneClient, +use plane_common::{ names::ProxyName, protocol::{MessageFromProxy, MessageToProxy, RouteInfoRequest}, types::ClusterName, + PlaneClient, }; use std::sync::Arc; use tokio::task::JoinHandle; diff --git a/plane/src/proxy/proxy_server.rs b/plane/src/proxy/proxy_server.rs index ea1778244..7c15de423 100644 --- a/plane/src/proxy/proxy_server.rs +++ b/plane/src/proxy/proxy_server.rs @@ -3,8 +3,8 @@ use super::{ request::{get_and_maybe_remove_bearer_token, subdomain_from_host}, route_map::RouteMap, }; -use crate::{names::Name, protocol::RouteInfo, SERVER_NAME}; use bytes::Bytes; +use plane_common::{names::Name, protocol::RouteInfo, version::SERVER_NAME}; use plane_dynamic_proxy::{ body::{simple_empty_body, SimpleBody}, hyper::{ diff --git a/plane/src/proxy/request.rs b/plane/src/proxy/request.rs index 6883c779e..2f933c973 100644 --- a/plane/src/proxy/request.rs +++ b/plane/src/proxy/request.rs @@ -1,4 +1,4 @@ -use crate::types::{BearerToken, ClusterName}; +use plane_common::types::{BearerToken, ClusterName}; use plane_dynamic_proxy::hyper::http::uri::{self, PathAndQuery}; use std::str::FromStr; diff --git a/plane/src/proxy/route_map.rs b/plane/src/proxy/route_map.rs index 2d1b5b95d..0967830d0 100644 --- a/plane/src/proxy/route_map.rs +++ b/plane/src/proxy/route_map.rs @@ -1,9 +1,9 @@ -use crate::{ +use lru::LruCache; +use plane_common::{ names::BackendName, protocol::{RouteInfo, RouteInfoRequest, RouteInfoResponse}, types::BearerToken, }; -use lru::LruCache; use std::{ collections::HashMap, num::NonZeroUsize, diff --git a/plane/src/typed_unix_socket/client.rs b/plane/src/typed_unix_socket/client.rs index 30436beac..35056b5e6 100644 --- a/plane/src/typed_unix_socket/client.rs +++ b/plane/src/typed_unix_socket/client.rs @@ -1,7 +1,9 @@ use super::WrappedMessage; -use crate::util::{random_token, ExponentialBackoff, GuardHandle}; +use crate::util::GuardHandle; use anyhow::{Error, Result}; use dashmap::DashMap; +use plane_common::exponential_backoff::ExponentialBackoff; +use plane_common::util::random_token; use serde::{Deserialize, Serialize}; use std::{clone::Clone, fmt::Debug, path::Path, sync::Arc}; use tokio::io::AsyncWriteExt; @@ -107,10 +109,10 @@ where async fn connect>(socket_path: P) -> UnixStream { let socket_path = socket_path.as_ref().to_path_buf(); let mut backoff = ExponentialBackoff::new( - chrono::Duration::milliseconds(10), - chrono::Duration::seconds(1), + Duration::from_millis(10), + Duration::from_secs(1), 1.5, - chrono::Duration::seconds(1), + Duration::from_secs(1), ); loop { match UnixStream::connect(&socket_path).await { diff --git a/plane/src/typed_unix_socket/mod.rs b/plane/src/typed_unix_socket/mod.rs index 131a05364..6caa61012 100644 --- a/plane/src/typed_unix_socket/mod.rs +++ b/plane/src/typed_unix_socket/mod.rs @@ -25,9 +25,10 @@ impl Drop for SocketPath { #[cfg(test)] mod tests { + use plane_common::util::random_string; + use super::client::TypedUnixSocketClient; use super::server::TypedUnixSocketServer; - use crate::util::random_string; use std::collections::HashSet; use std::env; use std::path::PathBuf; diff --git a/plane/src/util.rs b/plane/src/util.rs index 4b28301ee..0b1325bed 100644 --- a/plane/src/util.rs +++ b/plane/src/util.rs @@ -1,38 +1,8 @@ use chrono::Duration; use futures_util::Future; -use rand::{ - distributions::{Distribution, Uniform}, - Rng, -}; -use std::{ - net::{IpAddr, ToSocketAddrs}, - time::SystemTime, -}; +use std::net::{IpAddr, ToSocketAddrs}; use tokio::task::JoinHandle; -const ALLOWED_CHARS: &str = "abcdefghijklmnopqrstuvwxyz0123456789"; - -pub fn random_string() -> String { - let range = Uniform::new(0, ALLOWED_CHARS.len()); - let mut rng = rand::thread_rng(); - - range - .sample_iter(&mut rng) - .take(14) - .map(|i| ALLOWED_CHARS.chars().nth(i).expect("Index is always valid")) - .collect() -} - -pub fn random_token() -> String { - let mut token = [0u8; 32]; - rand::thread_rng().fill(&mut token); - data_encoding::BASE64URL_NOPAD.encode(&token) -} - -pub fn random_prefixed_string(prefix: &str) -> String { - format!("{}-{}", prefix, random_string()) -} - pub fn format_duration(duration: Duration) -> String { let mut parts = vec![]; @@ -63,81 +33,6 @@ pub fn format_duration(duration: Duration) -> String { } } -pub struct ExponentialBackoff { - initial_duration_millis: i64, - max_duration: Duration, - defer_duration: Duration, - multiplier: f64, - step: i32, - deferred_reset: Option, -} - -impl ExponentialBackoff { - pub fn new( - initial_duration: Duration, - max_duration: Duration, - multiplier: f64, - defer_duration: Duration, - ) -> Self { - let initial_duration_millis = initial_duration.num_milliseconds(); - - Self { - initial_duration_millis, - max_duration, - multiplier, - step: 0, - defer_duration, - deferred_reset: None, - } - } - - /// Reset the backoff, but only if `wait` is not called again for at least `defer_duration`. - pub fn defer_reset(&mut self) { - self.deferred_reset = Some( - SystemTime::now() - + self - .defer_duration - .to_std() - .expect("defer_duration is always valid"), - ); - } - - pub async fn wait(&mut self) { - if let Some(deferred_reset) = self.deferred_reset { - self.deferred_reset = None; - if SystemTime::now() > deferred_reset { - self.reset(); - return; - } - } - - let duration = self.initial_duration_millis as f64 * self.multiplier.powi(self.step); - let duration = - Duration::try_milliseconds(duration as i64).expect("duration is always valid"); - let duration = duration.min(self.max_duration); - - tokio::time::sleep(duration.to_std().expect("duration is always valid")).await; - - self.step += 1; - } - - pub fn reset(&mut self) { - self.deferred_reset = None; - self.step = 0; - } -} - -impl Default for ExponentialBackoff { - fn default() -> Self { - Self::new( - Duration::try_seconds(1).expect("duration is always valid"), - Duration::try_minutes(1).expect("duration is always valid"), - 1.1, - Duration::try_minutes(1).expect("duration is always valid"), - ) - } -} - #[derive(Debug)] pub struct GuardHandle { handle: JoinHandle<()>,