Begin to describe the orchestrator REST API with Swagger
This commit is contained in:
parent
3f7f0afcd1
commit
6cfcb6520a
|
@ -83,14 +83,6 @@ dependencies = [
|
|||
"safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.7.0"
|
||||
|
@ -186,17 +178,6 @@ dependencies = [
|
|||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.2.3"
|
||||
|
@ -269,35 +250,6 @@ dependencies = [
|
|||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "devise"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"devise_codegen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"devise_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "devise_codegen"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"devise_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "devise_core"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtoa"
|
||||
version = "0.4.3"
|
||||
|
@ -632,17 +584,6 @@ dependencies = [
|
|||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "isatty"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.3"
|
||||
|
@ -913,13 +854,6 @@ dependencies = [
|
|||
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "otto"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rocket 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "otto-agent"
|
||||
version = "0.1.0"
|
||||
|
@ -960,26 +894,6 @@ dependencies = [
|
|||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pear"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"pear_codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pear_codegen"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "1.0.1"
|
||||
|
@ -1223,66 +1137,6 @@ dependencies = [
|
|||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.13.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rocket"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pear 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rocket_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rocket_http 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rocket_codegen"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"devise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rocket_http 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rocket_http"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pear 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.13"
|
||||
|
@ -1462,11 +1316,6 @@ name = "stable_deref_trait"
|
|||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "state"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "string"
|
||||
version = "0.1.3"
|
||||
|
@ -1806,14 +1655,6 @@ dependencies = [
|
|||
"tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "traitobject"
|
||||
version = "0.1.0"
|
||||
|
@ -1913,11 +1754,6 @@ dependencies = [
|
|||
"traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "0.2.38"
|
||||
|
@ -2063,16 +1899,6 @@ dependencies = [
|
|||
"xml-rs 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5"
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
|
@ -2082,7 +1908,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
|
||||
"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4"
|
||||
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
|
||||
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
||||
"checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557"
|
||||
"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
|
||||
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
|
||||
|
@ -2098,7 +1923,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87"
|
||||
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1465f8134efa296b4c19db34d909637cb2bf0f7aaf21299e23e18fa29ac557cf"
|
||||
"checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67"
|
||||
"checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d"
|
||||
"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94"
|
||||
|
@ -2106,9 +1930,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13"
|
||||
"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4"
|
||||
"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
|
||||
"checksum devise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e04ba2d03c5fa0d954c061fc8c9c288badadffc272ebb87679a89846de3ed3"
|
||||
"checksum devise_codegen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "066ceb7928ca93a9bedc6d0e612a8a0424048b0ab1f75971b203d01420c055d7"
|
||||
"checksum devise_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf41c59b22b5e3ec0ea55c7847e5f358d340f3a8d6d53a5cf4f1564967f96487"
|
||||
"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd"
|
||||
"checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
|
||||
"checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
|
||||
|
@ -2138,7 +1959,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
|
||||
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
|
||||
"checksum iron 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8e17268922834707e1c29e8badbf9c712c9c43378e1b6a3388946baff10be2"
|
||||
"checksum isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e31a8281fc93ec9693494da65fbf28c0c2aa60a2eaec25dc58e2f31952e95edc"
|
||||
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
|
||||
|
@ -2174,8 +1994,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
|
||||
"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
|
||||
"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
|
||||
"checksum pear 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c26d2b92e47063ffce70d3e3b1bd097af121a9e0db07ca38a6cc1cf0cc85ff25"
|
||||
"checksum pear_codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "336db4a192cc7f54efeb0c4e11a9245394824cc3bcbd37ba3ff51240c35d7a6e"
|
||||
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
|
||||
"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18"
|
||||
"checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e"
|
||||
|
@ -2204,10 +2022,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
|
||||
"checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a"
|
||||
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
|
||||
"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a"
|
||||
"checksum rocket 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "242154377a85c2a9e036fc31ffc8c200b9e1f22a196e47baa3b57716606ca89d"
|
||||
"checksum rocket_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d907d6d458c859651c1cf4c8fa99b77685082bde0561db6a4600b365058f710"
|
||||
"checksum rocket_http 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba9d4f2ce5bba6e1b6d3100493bbad63879e99bbf6b4365d61e6f781daab324d"
|
||||
"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
|
||||
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
|
@ -2234,7 +2048,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013"
|
||||
"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15"
|
||||
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
|
||||
"checksum state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7345c971d1ef21ffdbd103a75990a15eb03604fc8b8852ca8cb418ee1a099028"
|
||||
"checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b"
|
||||
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
|
||||
"checksum swagger 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77341ed3930b4a752c7894896b3aa5000ef68ad5c3b359f98d4bd9d4c6dce3b7"
|
||||
|
@ -2264,7 +2077,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum tokio-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "772f4b04e560117fe3b0a53e490c16ddc8ba6ec437015d91fa385564996ed913"
|
||||
"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92"
|
||||
"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445"
|
||||
"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"
|
||||
"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
|
||||
"checksum try-lock 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2aa4715743892880f70885373966c83d73ef1b0838a664ef0c76fffd35e7c2"
|
||||
"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
|
||||
|
@ -2280,7 +2092,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||
"checksum unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f"
|
||||
"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
|
||||
"checksum url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)" = "cbaa8377a162d88e7d15db0cf110c8523453edcbc5bc66d2b6fffccffa34a068"
|
||||
"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
|
||||
"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
|
||||
|
@ -2301,5 +2112,3 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum xml-rs 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b46ee689ba7a669c08a1170c2348d2516c62dc461135c9e86b2f1f476e07be4a"
|
||||
"checksum xml-rs 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e1945e12e16b951721d7976520b0832496ef79c31602c7a29d950de79ba74621"
|
||||
"checksum xmltree 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "973f1a8be3ef2ce1388e0821093ce67d5eb4c2e897e88866e2ed6dd7a63920ed"
|
||||
"checksum yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d60c3b48c9cdec42fb06b3b84b5b087405e1fa1c644a1af3930e4dfafe93de48"
|
||||
"checksum yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71"
|
||||
|
|
1
Makefile
1
Makefile
|
@ -17,6 +17,7 @@ swagger: depends ## Generate the swagger stubs based on apispecs
|
|||
# It may be useful to read
|
||||
# https://github.com/swagger-api/swagger-codegen/pull/6613
|
||||
./scripts/swagger-codegen generate -l rust-server -i ./apispec/eventbus.yml -o eventbus/api -DpackageName=eventbus-api
|
||||
./scripts/swagger-codegen generate -l rust-server -i ./apispec/orchestrator.yml -o orchestrator/api -D packageName=orchestrator-api
|
||||
|
||||
depends: prereqs $(ANTLR) ## Download all dependencies
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
target/
|
|
@ -0,0 +1,114 @@
|
|||
---
|
||||
swagger: '2.0'
|
||||
info:
|
||||
description: 'This specification describes the Otto orchestrator'
|
||||
version: '1.0.0'
|
||||
title: Otto Orchestrator
|
||||
contact:
|
||||
email: 'rtyler@brokenco.de'
|
||||
license:
|
||||
name: 'GNU AGPL 3.0'
|
||||
url: 'https://www.gnu.org/licenses/agpl-3.0.en.html'
|
||||
host: 'localhost:3030'
|
||||
externalDocs:
|
||||
description: 'Find out more about Otto'
|
||||
url: 'https://github.com/rtyler/otto'
|
||||
basePath: '/v1'
|
||||
tags:
|
||||
schemes:
|
||||
- 'http'
|
||||
paths:
|
||||
/manifest/{agentId}:
|
||||
get:
|
||||
summary: 'Fetch manifest for execution by the given agent'
|
||||
description: |
|
||||
Return the full execution manifest for the given agent to execute.
|
||||
operationId: 'fetchManifest'
|
||||
produces:
|
||||
- 'application/json'
|
||||
- 'application/xml'
|
||||
parameters:
|
||||
- name: agentId
|
||||
in: path
|
||||
type: string
|
||||
required: true
|
||||
responses:
|
||||
200:
|
||||
description: 'Agent ID found and manifest generated'
|
||||
schema:
|
||||
$ref: '#/definitions/Manifest'
|
||||
400:
|
||||
description: 'Invalid request'
|
||||
securityDefinitions:
|
||||
definitions:
|
||||
Manifest:
|
||||
type: object
|
||||
description: 'Agent execution manifest'
|
||||
xml:
|
||||
name: 'Manifest'
|
||||
properties:
|
||||
self:
|
||||
type: string
|
||||
description: 'The identifier of the agent'
|
||||
services:
|
||||
type: object
|
||||
$ref: '#/definitions/Service'
|
||||
ops:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Operation'
|
||||
examples:
|
||||
self: 'otto-agent-1'
|
||||
services:
|
||||
$ref: '#/definitions/Service'
|
||||
ops:
|
||||
$ref: '#/definitions/Operation'
|
||||
|
||||
Service:
|
||||
type: object
|
||||
description: 'A service ID to URl mapping'
|
||||
xml:
|
||||
name: 'Service'
|
||||
properties:
|
||||
identifier:
|
||||
type: string
|
||||
description: 'Key to identify the different services'
|
||||
url:
|
||||
type: string
|
||||
description: 'Resolvable URL to access APIs for the given service'
|
||||
example:
|
||||
datastore: 'http://localhost:3031/'
|
||||
|
||||
Operation:
|
||||
type: object
|
||||
description: 'A discrete idempotent operation'
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: 'Globally unique ID to identify this specific operation in data stores, etc'
|
||||
context:
|
||||
type: string
|
||||
description: 'Generally unique context ID to group different operations in the same context'
|
||||
type:
|
||||
type: string
|
||||
description: 'Type of operation'
|
||||
$ref: '#/definitions/OperationType'
|
||||
data:
|
||||
type: object
|
||||
description: 'Operation type-specific data for the agent to use'
|
||||
example:
|
||||
id: '0xdeadbeef'
|
||||
context: '0x1'
|
||||
type: 'RUNPROC'
|
||||
data:
|
||||
script: 'echo "Hello World"'
|
||||
env:
|
||||
timeout_s: 600
|
||||
|
||||
OperationType:
|
||||
type: string
|
||||
description: 'Specific type of the given operation, implies different `data` fields'
|
||||
enum:
|
||||
- 'BEGINCTX'
|
||||
- 'ENDCTX'
|
||||
- 'RUNPROC'
|
|
@ -0,0 +1 @@
|
|||
server/target/
|
|
@ -13,7 +13,7 @@ To see how to make this your own, look here:
|
|||
[README](https://github.com/swagger-api/swagger-codegen/blob/master/README.md)
|
||||
|
||||
- API version: 1.0.0
|
||||
- Build date: 2019-03-28T04:19:04.173Z
|
||||
- Build date: 2019-05-25T01:36:57.200Z
|
||||
|
||||
This autogenerated project defines an API crate `eventbus-api` which contains:
|
||||
* An `Api` trait defining the API in Rust.
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
target
|
||||
Cargo.lock
|
||||
.cargo/
|
|
@ -0,0 +1,48 @@
|
|||
[package]
|
||||
name = "orchestrator-api"
|
||||
version = "1.0.0"
|
||||
authors = ["rtyler@brokenco.de"]
|
||||
description = "This specification describes the Otto orchestrator"
|
||||
license = "Unlicense"
|
||||
|
||||
[features]
|
||||
default = ["client", "server"]
|
||||
client = ["serde_json", "serde-xml-rs", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"]
|
||||
server = ["serde_json", "serde-xml-rs", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"]
|
||||
|
||||
[dependencies]
|
||||
# Required by example server.
|
||||
#
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
futures = "0.1"
|
||||
hyper = {version = "0.11", optional = true}
|
||||
hyper-tls = {version = "0.1.2", optional = true}
|
||||
swagger = "0.12.1"
|
||||
|
||||
# Not required by example server.
|
||||
#
|
||||
lazy_static = "0.2"
|
||||
log = "0.3.0"
|
||||
mime = "0.3.3"
|
||||
multipart = {version = "0.13.3", optional = true}
|
||||
native-tls = {version = "0.1.4", optional = true}
|
||||
openssl = {version = "0.9.14", optional = true}
|
||||
percent-encoding = {version = "1.0.0", optional = true}
|
||||
regex = {version = "0.2", optional = true}
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_ignored = {version = "0.0.4", optional = true}
|
||||
serde_json = {version = "1.0", optional = true}
|
||||
serde_urlencoded = {version = "0.5.1", optional = true}
|
||||
tokio-core = {version = "0.1.6", optional = true}
|
||||
tokio-proto = {version = "0.1.1", optional = true}
|
||||
tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]}
|
||||
url = {version = "1.5", optional = true}
|
||||
uuid = {version = "0.5", optional = true, features = ["serde", "v4"]}
|
||||
# ToDo: this should be updated to point at the official crate once
|
||||
# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
|
||||
serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master", optional = true}
|
||||
|
||||
[dev-dependencies]
|
||||
clap = "2.25"
|
||||
error-chain = "0.11"
|
|
@ -0,0 +1,105 @@
|
|||
# Rust API for orchestrator-api
|
||||
|
||||
This specification describes the Otto orchestrator
|
||||
|
||||
## Overview
|
||||
This client/server was generated by the [swagger-codegen]
|
||||
(https://github.com/swagger-api/swagger-codegen) project.
|
||||
By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.
|
||||
-
|
||||
|
||||
To see how to make this your own, look here:
|
||||
|
||||
[README](https://github.com/swagger-api/swagger-codegen/blob/master/README.md)
|
||||
|
||||
- API version: 1.0.0
|
||||
- Build date: 2019-05-25T01:36:58.848Z
|
||||
|
||||
This autogenerated project defines an API crate `orchestrator-api` which contains:
|
||||
* An `Api` trait defining the API in Rust.
|
||||
* Data types representing the underlying data model.
|
||||
* A `Client` type which implements `Api` and issues HTTP requests for each operation.
|
||||
* A router which accepts HTTP requests and invokes the appropriate `Api` method for each operation.
|
||||
|
||||
It also contains an example server and client which make use of `orchestrator-api`:
|
||||
* The example server starts up a web server using the `orchestrator-api` router,
|
||||
and supplies a trivial implementation of `Api` which returns failure for every operation.
|
||||
* The example client provides a CLI which lets you invoke any single operation on the
|
||||
`orchestrator-api` client by passing appropriate arguments on the command line.
|
||||
|
||||
You can use the example server and client as a basis for your own code.
|
||||
See below for [more detail on implementing a server](#writing-a-server).
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
Run examples with:
|
||||
|
||||
```
|
||||
cargo run --example <example-name>
|
||||
```
|
||||
|
||||
To pass in arguments to the examples, put them after `--`, for example:
|
||||
|
||||
```
|
||||
cargo run --example client -- --help
|
||||
```
|
||||
|
||||
### Running the server
|
||||
To run the server, follow these simple steps:
|
||||
|
||||
```
|
||||
cargo run --example server
|
||||
```
|
||||
|
||||
### Running a client
|
||||
To run a client, follow one of the following simple steps:
|
||||
|
||||
```
|
||||
cargo run --example client FetchManifest
|
||||
```
|
||||
|
||||
### HTTPS
|
||||
The examples can be run in HTTPS mode by passing in the flag `--https`, for example:
|
||||
|
||||
```
|
||||
cargo run --example server -- --https
|
||||
```
|
||||
|
||||
This will use the keys/certificates from the examples directory. Note that the server chain is signed with
|
||||
`CN=localhost`.
|
||||
|
||||
|
||||
## Writing a server
|
||||
|
||||
The server example is designed to form the basis for implementing your own server. Simply follow these steps.
|
||||
|
||||
* Set up a new Rust project, e.g., with `cargo init --bin`.
|
||||
* Insert `orchestrator-api` into the `members` array under [workspace] in the root `Cargo.toml`, e.g., `members = [ "orchestrator-api" ]`.
|
||||
* Add `orchestrator-api = {version = "1.0.0", path = "orchestrator-api"}` under `[dependencies]` in the root `Cargo.toml`.
|
||||
* Copy the `[dependencies]` and `[dev-dependencies]` from `orchestrator-api/Cargo.toml` into the root `Cargo.toml`'s `[dependencies]` section.
|
||||
* Copy all of the `[dev-dependencies]`, but only the `[dependencies]` that are required by the example server. These should be clearly indicated by comments.
|
||||
* Remove `"optional = true"` from each of these lines if present.
|
||||
|
||||
Each autogenerated API will contain an implementation stub and main entry point, which should be copied into your project the first time:
|
||||
```
|
||||
cp orchestrator-api/examples/server.rs src/main.rs
|
||||
cp orchestrator-api/examples/server_lib/mod.rs src/lib.rs
|
||||
cp orchestrator-api/examples/server_lib/server.rs src/server.rs
|
||||
```
|
||||
|
||||
Now
|
||||
|
||||
* From `src/main.rs`, remove the `mod server_lib;` line, and uncomment and fill in the `extern crate` line with the name of this server crate.
|
||||
* Move the block of imports "required by the service library" from `src/main.rs` to `src/lib.rs` and uncomment.
|
||||
* Change the `let server = server::Server {};` line to `let server = SERVICE_NAME::server().unwrap();` where `SERVICE_NAME` is the name of the server crate.
|
||||
* Run `cargo build` to check it builds.
|
||||
* Run `cargo fmt` to reformat the code.
|
||||
* Commit the result before making any further changes (lest format changes get confused with your own updates).
|
||||
|
||||
Now replace the implementations in `src/server.rs` with your own code as required.
|
||||
|
||||
## Updating your server to track API changes
|
||||
|
||||
Later, if the API changes, you can copy new sections from the autogenerated API stub into your implementation.
|
||||
Alternatively, implement the now-missing methods based on the compiler's error messages.
|
|
@ -0,0 +1,108 @@
|
|||
---
|
||||
swagger: "2.0"
|
||||
info:
|
||||
description: "This specification describes the Otto orchestrator"
|
||||
version: "1.0.0"
|
||||
title: "Otto Orchestrator"
|
||||
contact:
|
||||
email: "rtyler@brokenco.de"
|
||||
license:
|
||||
name: "GNU AGPL 3.0"
|
||||
url: "https://www.gnu.org/licenses/agpl-3.0.en.html"
|
||||
host: "ottodeploys.us"
|
||||
basePath: "/v1"
|
||||
schemes:
|
||||
- "https"
|
||||
- "http"
|
||||
paths:
|
||||
/manifest/{agentId}:
|
||||
get:
|
||||
summary: "Fetch manifest for execution by the given agent"
|
||||
description: "Return the full execution manifest for the given agent to execute.\n"
|
||||
operationId: "fetchManifest"
|
||||
produces:
|
||||
- "application/xml"
|
||||
- "application/json"
|
||||
parameters: []
|
||||
responses:
|
||||
200:
|
||||
description: "Successful enumeration"
|
||||
schema:
|
||||
type: "array"
|
||||
items:
|
||||
$ref: "#/definitions/Channel"
|
||||
x-responseId: "SuccessfulEnumeration"
|
||||
x-uppercaseResponseId: "SUCCESSFUL_ENUMERATION"
|
||||
uppercase_operation_id: "FETCH_MANIFEST"
|
||||
uppercase_data_type: "VEC<CHANNEL>"
|
||||
producesXml: true
|
||||
400:
|
||||
description: "Invalid request"
|
||||
x-responseId: "InvalidRequest"
|
||||
x-uppercaseResponseId: "INVALID_REQUEST"
|
||||
uppercase_operation_id: "FETCH_MANIFEST"
|
||||
operation_id: "fetch_manifest"
|
||||
uppercase_operation_id: "FETCH_MANIFEST"
|
||||
path: "/manifest/:agentId"
|
||||
PATH_ID: "MANIFEST_AGENTID"
|
||||
hasPathParams: false
|
||||
HttpMethod: "Get"
|
||||
definitions:
|
||||
Manifest:
|
||||
type: "object"
|
||||
properties:
|
||||
self:
|
||||
type: "string"
|
||||
description: "The identifier of the agent"
|
||||
services:
|
||||
type: "object"
|
||||
additionalProperties:
|
||||
$ref: "#/definitions/Service"
|
||||
ops:
|
||||
type: "array"
|
||||
items:
|
||||
$ref: "#/definitions/Operation"
|
||||
xml:
|
||||
name: "Manifest"
|
||||
upperCaseName: "MANIFEST"
|
||||
Service:
|
||||
type: "object"
|
||||
properties:
|
||||
identifier:
|
||||
type: "string"
|
||||
description: "Key to identify the different services"
|
||||
url:
|
||||
type: "string"
|
||||
description: "Resolvable URL to access APIs for the given service"
|
||||
xml:
|
||||
name: "Service"
|
||||
upperCaseName: "SERVICE"
|
||||
Operation:
|
||||
type: "object"
|
||||
properties:
|
||||
id:
|
||||
type: "string"
|
||||
description: "Globally unique ID to identify this specific operation in data\
|
||||
\ stores, etc"
|
||||
context:
|
||||
type: "string"
|
||||
description: "Generally unique context ID to group different operations in\
|
||||
\ the same context"
|
||||
type:
|
||||
description: "Type of operation"
|
||||
$ref: "#/definitions/OperationType"
|
||||
data:
|
||||
type: "object"
|
||||
description: "Operation type-specific data for the agent to use"
|
||||
properties: {}
|
||||
upperCaseName: "OPERATION"
|
||||
OperationType:
|
||||
type: "string"
|
||||
enum:
|
||||
- "BEGINCTX"
|
||||
- "ENDCTX"
|
||||
- "RUNPROC"
|
||||
upperCaseName: "OPERATIONTYPE"
|
||||
externalDocs:
|
||||
description: "Find out more about Otto"
|
||||
url: "https://github.com/rtyler/otto"
|
|
@ -0,0 +1,17 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICtjCCAZ4CCQDpKecRERZ0xDANBgkqhkiG9w0BAQsFADAdMQswCQYDVQQGEwJV
|
||||
UzEOMAwGA1UEAxMFTXkgQ0EwHhcNMTcwNTIzMTYwMDIzWhcNMTcwNjIyMTYwMDIz
|
||||
WjAdMQswCQYDVQQGEwJVUzEOMAwGA1UEAxMFTXkgQ0EwggEiMA0GCSqGSIb3DQEB
|
||||
AQUAA4IBDwAwggEKAoIBAQCt66py3x7sCSASRF2D05L5wkNDxAUjQKYx23W8Gbwv
|
||||
GMGykk89BIdU5LX1JB1cKiUOkoIxfwAYuWc2V/wzTvVV7+11besnk3uX1c9KiqUF
|
||||
LIX7kn/z5hzS4aelhKvH+MJlSZCSlp1ytpZbwo5GB5Pi2SGH56jDBiBoDRNBVdWL
|
||||
z4wH7TdrQjqWwNxIZumD5OGMtcfJyuX08iPiEOaslOeoMqzObhvjc9aUgjVjhqyA
|
||||
FkJGTXsi0oaD7oml+NE+mTNfEeZvEJQpLSjBY0OvQHzuHkyGBShBnfu/9x7/NRwd
|
||||
WaqsLiF7/re9KDGYdJwP7Cu6uxYfKAyWarp6h2mG/GIdAgMBAAEwDQYJKoZIhvcN
|
||||
AQELBQADggEBAGIl/VVIafeq/AJOQ9r7TzzB2ABJYr7NZa6bTu5O1jSp1Fonac15
|
||||
SZ8gvRxODgH22ZYSqghPG4xzq4J3hkytlQqm57ZEt2I2M3OqIp17Ndcc1xDYzpLl
|
||||
tA0FrVn6crQTM8vQkTDtGesaCWX+7Fir5dK7HnYWzfpSmsOpST07PfbNisEXKOxG
|
||||
Dj4lBL1OnhTjsJeymVS1pFvkKkrcEJO+IxFiHL3CDsWjcXB0Z+E1zBtPoYyYsNsO
|
||||
rBrjUxcZewF4xqWZhpW90Mt61fY2nRgU0uUwHcvDQUqvmzKcsqYa4mPKzfBI5mxo
|
||||
01Ta96cDD6pS5Y1hOflZ0g84f2g/7xBLLDA=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,82 @@
|
|||
#![allow(missing_docs, unused_variables, trivial_casts)]
|
||||
|
||||
extern crate orchestrator_api;
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate futures;
|
||||
#[allow(unused_extern_crates)]
|
||||
#[macro_use]
|
||||
extern crate swagger;
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate uuid;
|
||||
extern crate clap;
|
||||
extern crate tokio_core;
|
||||
|
||||
use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use futures::{Future, future, Stream, stream};
|
||||
use tokio_core::reactor;
|
||||
#[allow(unused_imports)]
|
||||
use orchestrator_api::{ApiNoContext, ContextWrapperExt,
|
||||
ApiError,
|
||||
FetchManifestResponse
|
||||
};
|
||||
use clap::{App, Arg};
|
||||
|
||||
fn main() {
|
||||
let matches = App::new("client")
|
||||
.arg(Arg::with_name("operation")
|
||||
.help("Sets the operation to run")
|
||||
.possible_values(&[
|
||||
"FetchManifest",
|
||||
])
|
||||
.required(true)
|
||||
.index(1))
|
||||
.arg(Arg::with_name("https")
|
||||
.long("https")
|
||||
.help("Whether to use HTTPS or not"))
|
||||
.arg(Arg::with_name("host")
|
||||
.long("host")
|
||||
.takes_value(true)
|
||||
.default_value("ottodeploys.us")
|
||||
.help("Hostname to contact"))
|
||||
.arg(Arg::with_name("port")
|
||||
.long("port")
|
||||
.takes_value(true)
|
||||
.default_value("8080")
|
||||
.help("Port to contact"))
|
||||
.get_matches();
|
||||
|
||||
let mut core = reactor::Core::new().unwrap();
|
||||
let is_https = matches.is_present("https");
|
||||
let base_url = format!("{}://{}:{}",
|
||||
if is_https { "https" } else { "http" },
|
||||
matches.value_of("host").unwrap(),
|
||||
matches.value_of("port").unwrap());
|
||||
let client = if matches.is_present("https") {
|
||||
// Using Simple HTTPS
|
||||
orchestrator_api::Client::try_new_https(core.handle(), &base_url, "examples/ca.pem")
|
||||
.expect("Failed to create HTTPS client")
|
||||
} else {
|
||||
// Using HTTP
|
||||
orchestrator_api::Client::try_new_http(core.handle(), &base_url)
|
||||
.expect("Failed to create HTTP client")
|
||||
};
|
||||
|
||||
let context: make_context_ty!(ContextBuilder, EmptyContext, Option<AuthData>, XSpanIdString) =
|
||||
make_context!(ContextBuilder, EmptyContext, None, XSpanIdString(self::uuid::Uuid::new_v4().to_string()));
|
||||
let client = client.with_context(context);
|
||||
|
||||
match matches.value_of("operation") {
|
||||
|
||||
Some("FetchManifest") => {
|
||||
let result = core.run(client.fetch_manifest());
|
||||
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &Has<XSpanIdString>).get().clone());
|
||||
},
|
||||
|
||||
_ => {
|
||||
panic!("Invalid operation provided")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
Certificate:
|
||||
Data:
|
||||
Version: 1 (0x0)
|
||||
Serial Number: 4096 (0x1000)
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
Issuer: C=US, CN=My CA
|
||||
Validity
|
||||
Not Before: May 23 16:00:23 2017 GMT
|
||||
Not After : Apr 29 16:00:23 2117 GMT
|
||||
Subject: CN=localhost, C=US
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:c9:d4:43:60:50:fc:d6:0f:38:4d:5d:5e:aa:7c:
|
||||
c0:5e:a9:ec:d9:93:78:d3:93:72:28:41:f5:08:a5:
|
||||
ea:ac:67:07:d7:1f:f7:7d:74:69:7e:46:89:20:4b:
|
||||
7a:2d:9b:02:08:e7:6f:0f:1d:0c:0f:c7:60:69:19:
|
||||
4b:df:7e:ca:75:94:0b:49:71:e3:6d:f2:e8:79:fd:
|
||||
ed:0a:94:67:55:f3:ca:6b:61:ba:58:b7:2e:dd:7b:
|
||||
ca:b9:02:9f:24:36:ac:26:8f:04:8f:81:c8:35:10:
|
||||
f4:aa:33:b2:24:16:f8:f7:1e:ea:f7:16:fe:fa:34:
|
||||
c3:dd:bb:2c:ba:7a:df:4d:e2:da:1e:e5:d2:28:44:
|
||||
6e:c8:96:e0:fd:09:0c:14:0c:31:dc:e0:ca:c1:a7:
|
||||
9b:bf:16:8c:f7:36:3f:1b:2e:dd:90:eb:45:78:51:
|
||||
bf:59:22:1e:c6:8c:0a:69:88:e5:03:5e:73:b7:fc:
|
||||
93:7f:1b:46:1b:97:68:c5:c0:8b:35:1f:bb:1e:67:
|
||||
7f:55:b7:3b:55:3f:ea:f2:ca:db:cc:52:cd:16:89:
|
||||
db:15:47:bd:f2:cd:6c:7a:d7:b4:1a:ac:c8:15:6c:
|
||||
6a:fb:77:c4:e9:f2:30:e0:14:24:66:65:6f:2a:e5:
|
||||
2d:cc:f6:81:ae:57:c8:d1:9b:38:90:dc:60:93:02:
|
||||
5e:cb
|
||||
Exponent: 65537 (0x10001)
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
1c:7c:39:e8:3d:49:b2:09:1e:68:5a:2f:74:18:f4:63:b5:8c:
|
||||
f6:e6:a1:e3:4d:95:90:99:ef:32:5c:34:40:e8:55:13:0e:e0:
|
||||
1c:be:cd:ab:3f:64:38:99:5e:2b:c1:81:53:a0:18:a8:f6:ee:
|
||||
6a:33:73:6c:9a:73:9d:86:08:5d:c7:11:38:46:4c:cd:a0:47:
|
||||
37:8f:fe:a6:50:a9:02:21:99:42:86:5e:47:fe:65:56:60:1d:
|
||||
16:53:86:bd:e4:63:c5:69:cf:fa:30:51:ab:a1:c3:50:53:cc:
|
||||
66:1c:4c:ff:3f:2a:39:4d:a2:8f:9d:d1:a7:8b:22:e4:78:69:
|
||||
24:06:83:4d:cc:0a:c0:87:69:9b:bc:80:a9:d2:b7:a5:23:84:
|
||||
7e:a2:32:26:7c:78:0e:bd:db:cd:3b:69:18:33:b8:44:ef:96:
|
||||
b4:99:86:ee:06:bd:51:1c:c7:a1:a4:0c:c4:4c:51:a0:df:ac:
|
||||
14:07:88:8e:d7:39:45:fe:52:e0:a3:4c:db:5d:7a:ab:4d:e4:
|
||||
ca:06:e8:bd:74:6f:46:e7:93:4a:4f:1b:67:e7:a5:9f:ef:9c:
|
||||
02:49:d1:f2:d5:e9:53:ee:09:21:ac:08:c8:15:f7:af:35:b9:
|
||||
4f:11:0f:43:ae:46:8e:fd:5b:8d:a3:4e:a7:2c:b7:25:ed:e4:
|
||||
e5:94:1d:e3
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICtTCCAZ0CAhAAMA0GCSqGSIb3DQEBCwUAMB0xCzAJBgNVBAYTAlVTMQ4wDAYD
|
||||
VQQDEwVNeSBDQTAgFw0xNzA1MjMxNjAwMjNaGA8yMTE3MDQyOTE2MDAyM1owITES
|
||||
MBAGA1UEAxMJbG9jYWxob3N0MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEB
|
||||
BQADggEPADCCAQoCggEBAMnUQ2BQ/NYPOE1dXqp8wF6p7NmTeNOTcihB9Qil6qxn
|
||||
B9cf9310aX5GiSBLei2bAgjnbw8dDA/HYGkZS99+ynWUC0lx423y6Hn97QqUZ1Xz
|
||||
ymthuli3Lt17yrkCnyQ2rCaPBI+ByDUQ9KozsiQW+Pce6vcW/vo0w927LLp6303i
|
||||
2h7l0ihEbsiW4P0JDBQMMdzgysGnm78WjPc2Pxsu3ZDrRXhRv1kiHsaMCmmI5QNe
|
||||
c7f8k38bRhuXaMXAizUfux5nf1W3O1U/6vLK28xSzRaJ2xVHvfLNbHrXtBqsyBVs
|
||||
avt3xOnyMOAUJGZlbyrlLcz2ga5XyNGbOJDcYJMCXssCAwEAATANBgkqhkiG9w0B
|
||||
AQsFAAOCAQEAHHw56D1JsgkeaFovdBj0Y7WM9uah402VkJnvMlw0QOhVEw7gHL7N
|
||||
qz9kOJleK8GBU6AYqPbuajNzbJpznYYIXccROEZMzaBHN4/+plCpAiGZQoZeR/5l
|
||||
VmAdFlOGveRjxWnP+jBRq6HDUFPMZhxM/z8qOU2ij53Rp4si5HhpJAaDTcwKwIdp
|
||||
m7yAqdK3pSOEfqIyJnx4Dr3bzTtpGDO4RO+WtJmG7ga9URzHoaQMxExRoN+sFAeI
|
||||
jtc5Rf5S4KNM2116q03kygbovXRvRueTSk8bZ+eln++cAknR8tXpU+4JIawIyBX3
|
||||
rzW5TxEPQ65Gjv1bjaNOpyy3Je3k5ZQd4w==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDJ1ENgUPzWDzhN
|
||||
XV6qfMBeqezZk3jTk3IoQfUIpeqsZwfXH/d9dGl+RokgS3otmwII528PHQwPx2Bp
|
||||
GUvffsp1lAtJceNt8uh5/e0KlGdV88prYbpYty7de8q5Ap8kNqwmjwSPgcg1EPSq
|
||||
M7IkFvj3Hur3Fv76NMPduyy6et9N4toe5dIoRG7IluD9CQwUDDHc4MrBp5u/Foz3
|
||||
Nj8bLt2Q60V4Ub9ZIh7GjAppiOUDXnO3/JN/G0Ybl2jFwIs1H7seZ39VtztVP+ry
|
||||
ytvMUs0WidsVR73yzWx617QarMgVbGr7d8Tp8jDgFCRmZW8q5S3M9oGuV8jRmziQ
|
||||
3GCTAl7LAgMBAAECggEBAKEd1q9j14KWYc64s6KLthGbutyxsinMMbxbct11fdIk
|
||||
6YhdF3fJ35ETg9IJDr6rWEN9ZRX+jStncNpVfFEs6ThVd3Eo/nI+EEGaaIkikR93
|
||||
X2a7fEPn7/yVHu70XdBN6L1bPDvHUeiy4W2hmRrgT90OjGm1rNRWHOm7yugOwIZu
|
||||
HclzbR9Ca7EInFnotUiDQm9sw9VKHbJHqWx6OORdZrxR2ytYs0Qkq0XpGMvti2HW
|
||||
7WAmKTg5QM8myXW7+/4iqb/u68wVBR2BBalShKmIf7lim9O3W2a1RjDdsvm/wNe9
|
||||
I+D+Iq825vpqkKXcrxYlpVg7hYiaQaW/MNsEb7lQRjECgYEA/RJYby0POW+/k0Jn
|
||||
jO8UmJVEMiuGa8WIUu/JJWMOmzRCukjSRNQOkt7niQrZPJYE8W6clM6RJTolWf9L
|
||||
IL6mIb+mRaoudUk8SHGDq7ho1iMg9GK8lhYxvKh1Q6uv8EyVSkgLknAEY0NANKC1
|
||||
zNdU5Dhven9aRX2gq9vP4XwMz2MCgYEAzCogQ7IFk+gkp3k491dOZnrGRoRCfuzo
|
||||
4CJtyKFgOSd7BjmpcKkj0IPfVBjw6GjMIxfQRMTQmxAjjWevH45vG8l0Iiwz/gSp
|
||||
81b5nsDEX5uv2Olcmcz5zxRFy36jOZ9ihMWinxcIlT2oDbyCdbruDKZq9ieJ9S8g
|
||||
4qGx0OkwE3kCgYEA7CmAiU89U9YqqttfEq/RQoqY91CSwmO10d+ej9seuEtOsdRf
|
||||
FIfnibulycdr7hP5TOxyBpO1802NqayJiWcgVYIpQf2MGTtcnCYCP+95NcvWZvj1
|
||||
EAJqK6nwtFO1fcOZ1ZXh5qfOEGujsPkAbsXLnKXlsiTCMvMHSxl3pu5Cbg0CgYBf
|
||||
JjbZNctRrjv+7Qj2hPLd4dQsIxGWc7ToWENP4J2mpVa5hQAJqFovoHXhjKohtk2F
|
||||
AWEn243Y5oGbMjo0e74edhmwn2cvuF64MM2vBem/ISCn98IXT6cQskMA3qkVfsl8
|
||||
VVs/x41ReGWs2TD3y0GMFbb9t1mdMfSiincDhNnKCQKBgGfeT4jKyYeCoCw4OLI1
|
||||
G75Gd0METt/IkppwODPpNwj3Rp9I5jctWZFA/3wCX/zk0HgBeou5AFNS4nQZ/X/L
|
||||
L9axbSdR7UJTGkT1r4gu3rLkPV4Tk+8XM03/JT2cofMlzQBuhvl1Pn4SgKowz7hl
|
||||
lS76ECw4Av3T0S34VW9Z5oye
|
||||
-----END PRIVATE KEY-----
|
|
@ -0,0 +1,75 @@
|
|||
//! Main binary entry point for orchestrator_api implementation.
|
||||
|
||||
#![allow(missing_docs)]
|
||||
|
||||
// Imports required by this file.
|
||||
// extern crate <name of this crate>;
|
||||
extern crate orchestrator_api;
|
||||
extern crate swagger;
|
||||
extern crate hyper;
|
||||
extern crate openssl;
|
||||
extern crate native_tls;
|
||||
extern crate tokio_proto;
|
||||
extern crate tokio_tls;
|
||||
extern crate clap;
|
||||
|
||||
// Imports required by server library.
|
||||
// extern crate orchestrator_api;
|
||||
// extern crate swagger;
|
||||
extern crate futures;
|
||||
extern crate chrono;
|
||||
#[macro_use]
|
||||
extern crate error_chain;
|
||||
|
||||
|
||||
use openssl::x509::X509_FILETYPE_PEM;
|
||||
use openssl::ssl::{SslAcceptorBuilder, SslMethod};
|
||||
use openssl::error::ErrorStack;
|
||||
use hyper::server::Http;
|
||||
use tokio_proto::TcpServer;
|
||||
use clap::{App, Arg};
|
||||
use swagger::auth::AllowAllAuthenticator;
|
||||
use swagger::EmptyContext;
|
||||
|
||||
mod server_lib;
|
||||
|
||||
// Builds an SSL implementation for Simple HTTPS from some hard-coded file names
|
||||
fn ssl() -> Result<SslAcceptorBuilder, ErrorStack> {
|
||||
let mut ssl = SslAcceptorBuilder::mozilla_intermediate_raw(SslMethod::tls())?;
|
||||
|
||||
// Server authentication
|
||||
ssl.set_private_key_file("examples/server-key.pem", X509_FILETYPE_PEM)?;
|
||||
ssl.set_certificate_chain_file("examples/server-chain.pem")?;
|
||||
ssl.check_private_key()?;
|
||||
|
||||
Ok(ssl)
|
||||
}
|
||||
|
||||
/// Create custom server, wire it to the autogenerated router,
|
||||
/// and pass it to the web server.
|
||||
fn main() {
|
||||
let matches = App::new("server")
|
||||
.arg(Arg::with_name("https")
|
||||
.long("https")
|
||||
.help("Whether to use HTTPS or not"))
|
||||
.get_matches();
|
||||
|
||||
let service_fn =
|
||||
orchestrator_api::server::auth::NewService::<_, EmptyContext>::new(
|
||||
AllowAllAuthenticator::new(
|
||||
server_lib::NewService::new(),
|
||||
"cosmo"
|
||||
)
|
||||
);
|
||||
|
||||
let addr = "127.0.0.1:8080".parse().expect("Failed to parse bind address");
|
||||
if matches.is_present("https") {
|
||||
let ssl = ssl().expect("Failed to load SSL keys");
|
||||
let builder: native_tls::TlsAcceptorBuilder = native_tls::backend::openssl::TlsAcceptorBuilderExt::from_openssl(ssl);
|
||||
let tls_acceptor = builder.build().expect("Failed to build TLS acceptor");
|
||||
TcpServer::new(tokio_tls::proto::Server::new(Http::new(), tls_acceptor), addr).serve(service_fn);
|
||||
} else {
|
||||
// Using HTTP
|
||||
TcpServer::new(Http::new(), addr).serve(service_fn);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
//! Main library entry point for orchestrator_api implementation.
|
||||
|
||||
mod server;
|
||||
|
||||
mod errors {
|
||||
error_chain!{}
|
||||
}
|
||||
|
||||
pub use self::errors::*;
|
||||
use std::io;
|
||||
use std::clone::Clone;
|
||||
use std::marker::PhantomData;
|
||||
use hyper;
|
||||
use orchestrator_api;
|
||||
use swagger::{Has, XSpanIdString};
|
||||
use swagger::auth::Authorization;
|
||||
|
||||
pub struct NewService<C>{
|
||||
marker: PhantomData<C>
|
||||
}
|
||||
|
||||
impl<C> NewService<C>{
|
||||
pub fn new() -> Self {
|
||||
NewService{marker:PhantomData}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> hyper::server::NewService for NewService<C> where C: Has<XSpanIdString> + Clone + 'static {
|
||||
type Request = (hyper::Request, C);
|
||||
type Response = hyper::Response;
|
||||
type Error = hyper::Error;
|
||||
type Instance = orchestrator_api::server::Service<server::Server<C>, C>;
|
||||
|
||||
/// Instantiate a new server.
|
||||
fn new_service(&self) -> io::Result<Self::Instance> {
|
||||
Ok(orchestrator_api::server::Service::new(server::Server::new()))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
//! Server implementation of orchestrator_api.
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use futures::{self, Future};
|
||||
use chrono;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use swagger;
|
||||
use swagger::{Has, XSpanIdString};
|
||||
|
||||
use orchestrator_api::{Api, ApiError,
|
||||
FetchManifestResponse
|
||||
};
|
||||
use orchestrator_api::models;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Server<C> {
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<C> Server<C> {
|
||||
pub fn new() -> Self {
|
||||
Server{marker: PhantomData}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> Api<C> for Server<C> where C: Has<XSpanIdString>{
|
||||
|
||||
/// Fetch manifest for execution by the given agent
|
||||
fn fetch_manifest(&self, context: &C) -> Box<Future<Item=FetchManifestResponse, Error=ApiError>> {
|
||||
let context = context.clone();
|
||||
println!("fetch_manifest() - X-Span-ID: {:?}", context.get().0.clone());
|
||||
Box::new(futures::failed("Generic failure".into()))
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,322 @@
|
|||
#![allow(unused_extern_crates)]
|
||||
extern crate tokio_core;
|
||||
extern crate native_tls;
|
||||
extern crate hyper_tls;
|
||||
extern crate openssl;
|
||||
extern crate mime;
|
||||
extern crate chrono;
|
||||
extern crate url;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
use hyper;
|
||||
use hyper::header::{Headers, ContentType};
|
||||
use hyper::Uri;
|
||||
use self::url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET};
|
||||
use futures;
|
||||
use futures::{Future, Stream};
|
||||
use futures::{future, stream};
|
||||
use self::tokio_core::reactor::Handle;
|
||||
use std::borrow::Cow;
|
||||
use std::io::{Read, Error, ErrorKind};
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use std::str;
|
||||
use std::str::FromStr;
|
||||
|
||||
use mimetypes;
|
||||
|
||||
use serde_json;
|
||||
use serde_xml_rs;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use std::collections::{HashMap, BTreeMap};
|
||||
#[allow(unused_imports)]
|
||||
use swagger;
|
||||
|
||||
use swagger::{ApiError, XSpanId, XSpanIdString, Has, AuthData};
|
||||
|
||||
use {Api,
|
||||
FetchManifestResponse
|
||||
};
|
||||
use models;
|
||||
|
||||
/// Convert input into a base path, e.g. "http://example:123". Also checks the scheme as it goes.
|
||||
fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result<String, ClientInitError> {
|
||||
// First convert to Uri, since a base path is a subset of Uri.
|
||||
let uri = Uri::from_str(input)?;
|
||||
|
||||
let scheme = uri.scheme().ok_or(ClientInitError::InvalidScheme)?;
|
||||
|
||||
// Check the scheme if necessary
|
||||
if let Some(correct_scheme) = correct_scheme {
|
||||
if scheme != correct_scheme {
|
||||
return Err(ClientInitError::InvalidScheme);
|
||||
}
|
||||
}
|
||||
|
||||
let host = uri.host().ok_or_else(|| ClientInitError::MissingHost)?;
|
||||
let port = uri.port().map(|x| format!(":{}", x)).unwrap_or_default();
|
||||
Ok(format!("{}://{}{}", scheme, host, port))
|
||||
}
|
||||
|
||||
/// A client that implements the API by making HTTP calls out to a server.
|
||||
#[derive(Clone)]
|
||||
pub struct Client {
|
||||
hyper_client: Arc<Box<hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=hyper::client::FutureResponse>>>,
|
||||
base_path: String,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Client {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Client {{ base_path: {} }}", self.base_path)
|
||||
}
|
||||
}
|
||||
|
||||
impl Client {
|
||||
|
||||
/// Create an HTTP client.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `handle` - tokio reactor handle to use for execution
|
||||
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
|
||||
pub fn try_new_http(handle: Handle, base_path: &str) -> Result<Client, ClientInitError> {
|
||||
let http_connector = swagger::http_connector();
|
||||
Self::try_new_with_connector::<hyper::client::HttpConnector>(
|
||||
handle,
|
||||
base_path,
|
||||
Some("http"),
|
||||
http_connector,
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a client with a TLS connection to the server.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `handle` - tokio reactor handle to use for execution
|
||||
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
|
||||
/// * `ca_certificate` - Path to CA certificate used to authenticate the server
|
||||
pub fn try_new_https<CA>(
|
||||
handle: Handle,
|
||||
base_path: &str,
|
||||
ca_certificate: CA,
|
||||
) -> Result<Client, ClientInitError>
|
||||
where
|
||||
CA: AsRef<Path>,
|
||||
{
|
||||
let https_connector = swagger::https_connector(ca_certificate);
|
||||
Self::try_new_with_connector::<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>(
|
||||
handle,
|
||||
base_path,
|
||||
Some("https"),
|
||||
https_connector,
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a client with a mutually authenticated TLS connection to the server.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `handle` - tokio reactor handle to use for execution
|
||||
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
|
||||
/// * `ca_certificate` - Path to CA certificate used to authenticate the server
|
||||
/// * `client_key` - Path to the client private key
|
||||
/// * `client_certificate` - Path to the client's public certificate associated with the private key
|
||||
pub fn try_new_https_mutual<CA, K, C, T>(
|
||||
handle: Handle,
|
||||
base_path: &str,
|
||||
ca_certificate: CA,
|
||||
client_key: K,
|
||||
client_certificate: C,
|
||||
) -> Result<Client, ClientInitError>
|
||||
where
|
||||
CA: AsRef<Path>,
|
||||
K: AsRef<Path>,
|
||||
C: AsRef<Path>,
|
||||
{
|
||||
let https_connector =
|
||||
swagger::https_mutual_connector(ca_certificate, client_key, client_certificate);
|
||||
Self::try_new_with_connector::<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>(
|
||||
handle,
|
||||
base_path,
|
||||
Some("https"),
|
||||
https_connector,
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a client with a custom implementation of hyper::client::Connect.
|
||||
///
|
||||
/// Intended for use with custom implementations of connect for e.g. protocol logging
|
||||
/// or similar functionality which requires wrapping the transport layer. When wrapping a TCP connection,
|
||||
/// this function should be used in conjunction with
|
||||
/// `swagger::{http_connector, https_connector, https_mutual_connector}`.
|
||||
///
|
||||
/// For ordinary tcp connections, prefer the use of `try_new_http`, `try_new_https`
|
||||
/// and `try_new_https_mutual`, to avoid introducing a dependency on the underlying transport layer.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `handle` - tokio reactor handle to use for execution
|
||||
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
|
||||
/// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")`
|
||||
/// * `connector_fn` - Function which returns an implementation of `hyper::client::Connect`
|
||||
pub fn try_new_with_connector<C>(
|
||||
handle: Handle,
|
||||
base_path: &str,
|
||||
protocol: Option<&'static str>,
|
||||
connector_fn: Box<Fn(&Handle) -> C + Send + Sync>,
|
||||
) -> Result<Client, ClientInitError>
|
||||
where
|
||||
C: hyper::client::Connect + hyper::client::Service,
|
||||
{
|
||||
let connector = connector_fn(&handle);
|
||||
let hyper_client = Box::new(hyper::Client::configure().connector(connector).build(
|
||||
&handle,
|
||||
));
|
||||
|
||||
Ok(Client {
|
||||
hyper_client: Arc::new(hyper_client),
|
||||
base_path: into_base_path(base_path, protocol)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Constructor for creating a `Client` by passing in a pre-made `hyper` client.
|
||||
///
|
||||
/// One should avoid relying on this function if possible, since it adds a dependency on the underlying transport
|
||||
/// implementation, which it would be better to abstract away. Therefore, using this function may lead to a loss of
|
||||
/// code generality, which may make it harder to move the application to a serverless environment, for example.
|
||||
///
|
||||
/// The reason for this function's existence is to support legacy test code, which did mocking at the hyper layer.
|
||||
/// This is not a recommended way to write new tests. If other reasons are found for using this function, they
|
||||
/// should be mentioned here.
|
||||
pub fn try_new_with_hyper_client(hyper_client: Arc<Box<hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=hyper::client::FutureResponse>>>,
|
||||
handle: Handle,
|
||||
base_path: &str)
|
||||
-> Result<Client, ClientInitError>
|
||||
{
|
||||
Ok(Client {
|
||||
hyper_client: hyper_client,
|
||||
base_path: into_base_path(base_path, None)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> Api<C> for Client where C: Has<XSpanIdString> {
|
||||
|
||||
fn fetch_manifest(&self, context: &C) -> Box<Future<Item=FetchManifestResponse, Error=ApiError>> {
|
||||
|
||||
|
||||
let uri = format!(
|
||||
"{}/v1/manifest/{agentId}",
|
||||
self.base_path
|
||||
);
|
||||
|
||||
let uri = match Uri::from_str(&uri) {
|
||||
Ok(uri) => uri,
|
||||
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build URI: {}", err))))),
|
||||
};
|
||||
|
||||
let mut request = hyper::Request::new(hyper::Method::Get, uri);
|
||||
|
||||
|
||||
|
||||
request.headers_mut().set(XSpanId((context as &Has<XSpanIdString>).get().0.clone()));
|
||||
|
||||
|
||||
|
||||
|
||||
Box::new(self.hyper_client.call(request)
|
||||
.map_err(|e| ApiError(format!("No response received: {}", e)))
|
||||
.and_then(|mut response| {
|
||||
match response.status().as_u16() {
|
||||
200 => {
|
||||
let body = response.body();
|
||||
Box::new(
|
||||
|
||||
body
|
||||
.concat2()
|
||||
.map_err(|e| ApiError(format!("Failed to read response: {}", e)))
|
||||
.and_then(|body| str::from_utf8(&body)
|
||||
.map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))
|
||||
.and_then(|body|
|
||||
|
||||
// ToDo: this will move to swagger-rs and become a standard From conversion trait
|
||||
// once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
|
||||
serde_xml_rs::from_str::<Vec<models::Channel>>(body)
|
||||
.map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))
|
||||
|
||||
))
|
||||
.map(move |body|
|
||||
FetchManifestResponse::SuccessfulEnumeration(body)
|
||||
)
|
||||
) as Box<Future<Item=_, Error=_>>
|
||||
},
|
||||
400 => {
|
||||
let body = response.body();
|
||||
Box::new(
|
||||
|
||||
future::ok(
|
||||
FetchManifestResponse::InvalidRequest
|
||||
)
|
||||
) as Box<Future<Item=_, Error=_>>
|
||||
},
|
||||
code => {
|
||||
let headers = response.headers().clone();
|
||||
Box::new(response.body()
|
||||
.take(100)
|
||||
.concat2()
|
||||
.then(move |body|
|
||||
future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}",
|
||||
code,
|
||||
headers,
|
||||
match body {
|
||||
Ok(ref body) => match str::from_utf8(body) {
|
||||
Ok(body) => Cow::from(body),
|
||||
Err(e) => Cow::from(format!("<Body was not UTF8: {:?}>", e)),
|
||||
},
|
||||
Err(e) => Cow::from(format!("<Failed to read body: {}>", e)),
|
||||
})))
|
||||
)
|
||||
) as Box<Future<Item=_, Error=_>>
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ClientInitError {
|
||||
InvalidScheme,
|
||||
InvalidUri(hyper::error::UriError),
|
||||
MissingHost,
|
||||
SslError(openssl::error::ErrorStack)
|
||||
}
|
||||
|
||||
impl From<hyper::error::UriError> for ClientInitError {
|
||||
fn from(err: hyper::error::UriError) -> ClientInitError {
|
||||
ClientInitError::InvalidUri(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<openssl::error::ErrorStack> for ClientInitError {
|
||||
fn from(err: openssl::error::ErrorStack) -> ClientInitError {
|
||||
ClientInitError::SslError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ClientInitError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
(self as &fmt::Debug).fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for ClientInitError {
|
||||
fn description(&self) -> &str {
|
||||
"Failed to produce a hyper client."
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)]
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate serde_json;
|
||||
|
||||
extern crate serde_xml_rs;
|
||||
extern crate futures;
|
||||
extern crate chrono;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module.
|
||||
#[cfg(any(feature = "client", feature = "server"))]
|
||||
#[macro_use]
|
||||
extern crate hyper;
|
||||
|
||||
extern crate swagger;
|
||||
|
||||
use futures::Stream;
|
||||
use std::io::Error;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub use futures::Future;
|
||||
|
||||
#[cfg(any(feature = "client", feature = "server"))]
|
||||
mod mimetypes;
|
||||
|
||||
pub use swagger::{ApiError, ContextWrapper};
|
||||
|
||||
pub const BASE_PATH: &'static str = "/v1";
|
||||
pub const API_VERSION: &'static str = "1.0.0";
|
||||
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum FetchManifestResponse {
|
||||
/// Successful enumeration
|
||||
SuccessfulEnumeration ( Vec<models::Channel> ) ,
|
||||
/// Invalid request
|
||||
InvalidRequest ,
|
||||
}
|
||||
|
||||
|
||||
/// API
|
||||
pub trait Api<C> {
|
||||
|
||||
/// Fetch manifest for execution by the given agent
|
||||
fn fetch_manifest(&self, context: &C) -> Box<Future<Item=FetchManifestResponse, Error=ApiError>>;
|
||||
|
||||
}
|
||||
|
||||
/// API without a `Context`
|
||||
pub trait ApiNoContext {
|
||||
|
||||
/// Fetch manifest for execution by the given agent
|
||||
fn fetch_manifest(&self) -> Box<Future<Item=FetchManifestResponse, Error=ApiError>>;
|
||||
|
||||
}
|
||||
|
||||
/// Trait to extend an API to make it easy to bind it to a context.
|
||||
pub trait ContextWrapperExt<'a, C> where Self: Sized {
|
||||
/// Binds this API to a context.
|
||||
fn with_context(self: &'a Self, context: C) -> ContextWrapper<'a, Self, C>;
|
||||
}
|
||||
|
||||
impl<'a, T: Api<C> + Sized, C> ContextWrapperExt<'a, C> for T {
|
||||
fn with_context(self: &'a T, context: C) -> ContextWrapper<'a, T, C> {
|
||||
ContextWrapper::<T, C>::new(self, context)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Api<C>, C> ApiNoContext for ContextWrapper<'a, T, C> {
|
||||
|
||||
/// Fetch manifest for execution by the given agent
|
||||
fn fetch_manifest(&self) -> Box<Future<Item=FetchManifestResponse, Error=ApiError>> {
|
||||
self.api().fetch_manifest(&self.context())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
pub mod client;
|
||||
|
||||
// Re-export Client as a top-level name
|
||||
#[cfg(feature = "client")]
|
||||
pub use self::client::Client;
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
pub mod server;
|
||||
|
||||
// Re-export router() as a top-level name
|
||||
#[cfg(feature = "server")]
|
||||
pub use self::server::Service;
|
||||
|
||||
pub mod models;
|
|
@ -0,0 +1,17 @@
|
|||
/// mime types for requests and responses
|
||||
|
||||
pub mod responses {
|
||||
use hyper::mime::*;
|
||||
|
||||
// The macro is called per-operation to beat the recursion limit
|
||||
/// Create Mime objects for the response content types for FetchManifest
|
||||
lazy_static! {
|
||||
pub static ref FETCH_MANIFEST_SUCCESSFUL_ENUMERATION: Mime = "application/xml".parse().unwrap();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub mod requests {
|
||||
use hyper::mime::*;
|
||||
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
|
||||
extern crate chrono;
|
||||
extern crate uuid;
|
||||
|
||||
use serde_xml_rs;
|
||||
use serde::ser::Serializer;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use models;
|
||||
use swagger;
|
||||
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename = "Manifest")]
|
||||
pub struct Manifest {
|
||||
/// The identifier of the agent
|
||||
#[serde(rename = "self")]
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub _self: Option<String>,
|
||||
|
||||
#[serde(rename = "services")]
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub services: Option<HashMap<String, models::Service>>,
|
||||
|
||||
#[serde(rename = "ops")]
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub ops: Option<Vec<models::Operation>>,
|
||||
|
||||
}
|
||||
|
||||
impl Manifest {
|
||||
pub fn new() -> Manifest {
|
||||
Manifest {
|
||||
_self: None,
|
||||
services: None,
|
||||
ops: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Operation {
|
||||
/// Globally unique ID to identify this specific operation in data stores, etc
|
||||
#[serde(rename = "id")]
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub id: Option<String>,
|
||||
|
||||
/// Generally unique context ID to group different operations in the same context
|
||||
#[serde(rename = "context")]
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub context: Option<String>,
|
||||
|
||||
/// Type of operation
|
||||
#[serde(rename = "type")]
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub _type: Option<models::OperationType>,
|
||||
|
||||
/// Operation type-specific data for the agent to use
|
||||
#[serde(rename = "data")]
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub data: Option<Object>,
|
||||
|
||||
}
|
||||
|
||||
impl Operation {
|
||||
pub fn new() -> Operation {
|
||||
Operation {
|
||||
id: None,
|
||||
context: None,
|
||||
_type: None,
|
||||
data: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Enumeration of values.
|
||||
/// Since this enum's variants do not hold data, we can easily define them them as `#[repr(C)]`
|
||||
/// which helps with FFI.
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize, Eq, Ord)]
|
||||
pub enum OperationType {
|
||||
#[serde(rename = "BEGINCTX")]
|
||||
BEGINCTX,
|
||||
#[serde(rename = "ENDCTX")]
|
||||
ENDCTX,
|
||||
#[serde(rename = "RUNPROC")]
|
||||
RUNPROC,
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for OperationType {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
match *self {
|
||||
OperationType::BEGINCTX => write!(f, "{}", "BEGINCTX"),
|
||||
OperationType::ENDCTX => write!(f, "{}", "ENDCTX"),
|
||||
OperationType::RUNPROC => write!(f, "{}", "RUNPROC"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::str::FromStr for OperationType {
|
||||
type Err = ();
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"BEGINCTX" => Ok(OperationType::BEGINCTX),
|
||||
"ENDCTX" => Ok(OperationType::ENDCTX),
|
||||
"RUNPROC" => Ok(OperationType::RUNPROC),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename = "Service")]
|
||||
pub struct Service {
|
||||
/// Key to identify the different services
|
||||
#[serde(rename = "identifier")]
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub identifier: Option<String>,
|
||||
|
||||
/// Resolvable URL to access APIs for the given service
|
||||
#[serde(rename = "url")]
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub url: Option<String>,
|
||||
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn new() -> Service {
|
||||
Service {
|
||||
identifier: None,
|
||||
url: None,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
use std::io;
|
||||
use std::marker::PhantomData;
|
||||
use std::default::Default;
|
||||
use hyper;
|
||||
use hyper::{Request, Response, Error, StatusCode};
|
||||
use server::url::form_urlencoded;
|
||||
use swagger::auth::{Authorization, AuthData, Scopes};
|
||||
use swagger::{Has, Pop, Push, XSpanIdString};
|
||||
use Api;
|
||||
|
||||
pub struct NewService<T, C>
|
||||
where
|
||||
C: Default + Push<XSpanIdString>,
|
||||
C::Result: Push<Option<AuthData>>,
|
||||
T: hyper::server::NewService<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
|
||||
{
|
||||
inner: T,
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<T, C> NewService<T, C>
|
||||
where
|
||||
C: Default + Push<XSpanIdString>,
|
||||
C::Result: Push<Option<AuthData>>,
|
||||
T: hyper::server::NewService<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error> + 'static,
|
||||
{
|
||||
pub fn new(inner: T) -> NewService<T, C> {
|
||||
NewService {
|
||||
inner,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C> hyper::server::NewService for NewService<T, C>
|
||||
where
|
||||
C: Default + Push<XSpanIdString>,
|
||||
C::Result: Push<Option<AuthData>>,
|
||||
T: hyper::server::NewService<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error> + 'static,
|
||||
{
|
||||
type Request = Request;
|
||||
type Response = Response;
|
||||
type Error = Error;
|
||||
type Instance = Service<T::Instance, C>;
|
||||
|
||||
fn new_service(&self) -> Result<Self::Instance, io::Error> {
|
||||
self.inner.new_service().map(|s| Service::new(s))
|
||||
}
|
||||
}
|
||||
|
||||
/// Middleware to extract authentication data from request
|
||||
pub struct Service<T, C>
|
||||
where
|
||||
C: Default + Push<XSpanIdString>,
|
||||
C::Result: Push<Option<AuthData>>,
|
||||
T: hyper::server::Service<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
|
||||
{
|
||||
inner: T,
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<T, C> Service<T, C>
|
||||
where
|
||||
C: Default + Push<XSpanIdString>,
|
||||
C::Result: Push<Option<AuthData>>,
|
||||
T: hyper::server::Service<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
|
||||
{
|
||||
pub fn new(inner: T) -> Service<T, C> {
|
||||
Service {
|
||||
inner,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C> hyper::server::Service for Service<T, C>
|
||||
where
|
||||
C: Default + Push<XSpanIdString>,
|
||||
C::Result: Push<Option<AuthData>>,
|
||||
T: hyper::server::Service<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
|
||||
{
|
||||
type Request = Request;
|
||||
type Response = Response;
|
||||
type Error = Error;
|
||||
type Future = T::Future;
|
||||
|
||||
fn call(&self, req: Self::Request) -> Self::Future {
|
||||
let context = C::default().push(XSpanIdString::get_or_generate(&req));
|
||||
|
||||
|
||||
let context = context.push(None);
|
||||
return self.inner.call((req, context));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,187 @@
|
|||
#![allow(unused_extern_crates)]
|
||||
extern crate serde_ignored;
|
||||
extern crate tokio_core;
|
||||
extern crate native_tls;
|
||||
extern crate hyper_tls;
|
||||
extern crate openssl;
|
||||
extern crate mime;
|
||||
extern crate uuid;
|
||||
extern crate chrono;
|
||||
|
||||
extern crate percent_encoding;
|
||||
extern crate url;
|
||||
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::marker::PhantomData;
|
||||
use futures::{Future, future, Stream, stream};
|
||||
use hyper;
|
||||
use hyper::{Request, Response, Error, StatusCode};
|
||||
use hyper::header::{Headers, ContentType};
|
||||
use self::url::form_urlencoded;
|
||||
use mimetypes;
|
||||
|
||||
|
||||
use serde_json;
|
||||
use serde_xml_rs;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use std::collections::{HashMap, BTreeMap};
|
||||
#[allow(unused_imports)]
|
||||
use swagger;
|
||||
use std::io;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
pub use swagger::auth::Authorization;
|
||||
use swagger::{ApiError, XSpanId, XSpanIdString, Has};
|
||||
use swagger::auth::Scopes;
|
||||
|
||||
use {Api,
|
||||
FetchManifestResponse
|
||||
};
|
||||
#[allow(unused_imports)]
|
||||
use models;
|
||||
|
||||
pub mod auth;
|
||||
|
||||
header! { (Warning, "Warning") => [String] }
|
||||
|
||||
mod paths {
|
||||
extern crate regex;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref GLOBAL_REGEX_SET: regex::RegexSet = regex::RegexSet::new(&[
|
||||
r"^/v1/manifest/(?P<agentId>[^/?#]*)$"
|
||||
]).unwrap();
|
||||
}
|
||||
pub static ID_MANIFEST_AGENTID: usize = 0;
|
||||
}
|
||||
|
||||
pub struct NewService<T, C> {
|
||||
api_impl: Arc<T>,
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<T, C> NewService<T, C>
|
||||
where
|
||||
T: Api<C> + Clone + 'static,
|
||||
C: Has<XSpanIdString> + 'static
|
||||
{
|
||||
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> NewService<T, C> {
|
||||
NewService{api_impl: api_impl.into(), marker: PhantomData}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C> hyper::server::NewService for NewService<T, C>
|
||||
where
|
||||
T: Api<C> + Clone + 'static,
|
||||
C: Has<XSpanIdString> + 'static
|
||||
{
|
||||
type Request = (Request, C);
|
||||
type Response = Response;
|
||||
type Error = Error;
|
||||
type Instance = Service<T, C>;
|
||||
|
||||
fn new_service(&self) -> Result<Self::Instance, io::Error> {
|
||||
Ok(Service::new(self.api_impl.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Service<T, C> {
|
||||
api_impl: Arc<T>,
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<T, C> Service<T, C>
|
||||
where
|
||||
T: Api<C> + Clone + 'static,
|
||||
C: Has<XSpanIdString> + 'static {
|
||||
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> Service<T, C> {
|
||||
Service{api_impl: api_impl.into(), marker: PhantomData}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C> hyper::server::Service for Service<T, C>
|
||||
where
|
||||
T: Api<C> + Clone + 'static,
|
||||
C: Has<XSpanIdString> + 'static
|
||||
{
|
||||
type Request = (Request, C);
|
||||
type Response = Response;
|
||||
type Error = Error;
|
||||
type Future = Box<Future<Item=Response, Error=Error>>;
|
||||
|
||||
fn call(&self, (req, mut context): Self::Request) -> Self::Future {
|
||||
let api_impl = self.api_impl.clone();
|
||||
let (method, uri, _, headers, body) = req.deconstruct();
|
||||
let path = paths::GLOBAL_REGEX_SET.matches(uri.path());
|
||||
match &method {
|
||||
|
||||
// FetchManifest - GET /manifest/{agentId}
|
||||
&hyper::Method::Get if path.matched(paths::ID_MANIFEST_AGENTID) => {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Box::new({
|
||||
{{
|
||||
|
||||
Box::new(api_impl.fetch_manifest(&context)
|
||||
.then(move |result| {
|
||||
let mut response = Response::new();
|
||||
response.headers_mut().set(XSpanId((&context as &Has<XSpanIdString>).get().0.to_string()));
|
||||
|
||||
match result {
|
||||
Ok(rsp) => match rsp {
|
||||
FetchManifestResponse::SuccessfulEnumeration
|
||||
|
||||
(body)
|
||||
|
||||
|
||||
=> {
|
||||
response.set_status(StatusCode::try_from(200).unwrap());
|
||||
|
||||
response.headers_mut().set(ContentType(mimetypes::responses::FETCH_MANIFEST_SUCCESSFUL_ENUMERATION.clone()));
|
||||
|
||||
|
||||
let body = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize");
|
||||
|
||||
response.set_body(body);
|
||||
},
|
||||
FetchManifestResponse::InvalidRequest
|
||||
|
||||
|
||||
=> {
|
||||
response.set_status(StatusCode::try_from(400).unwrap());
|
||||
|
||||
},
|
||||
},
|
||||
Err(_) => {
|
||||
// Application code returned an error. This should not happen, as the implementation should
|
||||
// return a valid response.
|
||||
response.set_status(StatusCode::InternalServerError);
|
||||
response.set_body("An internal error occurred");
|
||||
},
|
||||
}
|
||||
|
||||
future::ok(response)
|
||||
}
|
||||
))
|
||||
|
||||
}}
|
||||
}) as Box<Future<Item=Response, Error=Error>>
|
||||
|
||||
|
||||
},
|
||||
|
||||
|
||||
_ => Box::new(future::ok(Response::new().with_status(StatusCode::NotFound))) as Box<Future<Item=Response, Error=Error>>,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
exec docker run --rm -ti \
|
||||
-p 8080:8080 \
|
||||
-e SWAGGER_JSON=/data/apispec/orchestrator.yml \
|
||||
-v $PWD:/data \
|
||||
swaggerapi/swagger-ui:latest
|
Loading…
Reference in New Issue