diff --git a/.circleci/config.yml b/.circleci/config.yml index 4fec5ecb2c..ab9f9f9e0c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -631,10 +631,8 @@ workflows: parameters: path: - resources/aws-rds - - resources/metadata - resources/persist - resources/qdrant - - resources/secrets - resources/shared-db - resources/turso - resources/opendal diff --git a/cargo-shuttle/src/lib.rs b/cargo-shuttle/src/lib.rs index eca66eb3dc..7409f0e382 100644 --- a/cargo-shuttle/src/lib.rs +++ b/cargo-shuttle/src/lib.rs @@ -448,7 +448,8 @@ impl Shuttle { } else { get_templates_schema() .await - .map_err(|_| { + .map_err(|e| { + error!(err = %e, "Failed to get templates"); println!( "{}", "Failed to look up template list. Falling back to internal list." diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 9935ad3adb..7072046057 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -26,7 +26,7 @@ mod shuttle_main; /// | `ShuttlePoem` | [shuttle-poem](https://crates.io/crates/shuttle-poem) | [poem](https://docs.rs/poem/2.0) | 2.0 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/poem/hello-world) | /// | `ShuttleRocket` | [shuttle-rocket](https://crates.io/crates/shuttle-rocket) | [rocket](https://docs.rs/rocket/0.5) | 0.5 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/rocket/hello-world) | /// | `ShuttleSalvo` | [shuttle-salvo](https://crates.io/crates/shuttle-salvo) | [salvo](https://docs.rs/salvo/0.63) | 0.63 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/salvo/hello-world) | -/// | `ShuttleSerenity` | [shuttle-serenity](https://crates.io/crates/shuttle-serenity | [serenity](https://docs.rs/serenity/0.12) and [poise](https://docs.rs/poise/0.6) | 0.12 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/serenity/hello-world) | +/// | `ShuttleSerenity` | [shuttle-serenity](https://crates.io/crates/shuttle-serenity) | [serenity](https://docs.rs/serenity/0.12) and [poise](https://docs.rs/poise/0.6) | 0.12 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/serenity/hello-world) | /// | `ShuttleThruster` | [shuttle-thruster](https://crates.io/crates/shuttle-thruster) | [thruster](https://docs.rs/thruster/1.3) | 1.3 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/thruster/hello-world) | /// | `ShuttleTower` | [shuttle-tower](https://crates.io/crates/shuttle-tower) | [tower](https://docs.rs/tower/0.4) | 0.4 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/tower/hello-world) | /// | `ShuttleTide` | [shuttle-tide](https://crates.io/crates/shuttle-tide) | [tide](https://docs.rs/tide/0.16) | 0.16 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/tide/hello-world) | diff --git a/common/src/resource.rs b/common/src/resource.rs index b2d7b9c9bb..53931733e7 100644 --- a/common/src/resource.rs +++ b/common/src/resource.rs @@ -56,10 +56,10 @@ pub struct Response { /// The type of this resource. pub r#type: Type, - /// The config used when creating this resource. Use the [Self::r#type] to know how to parse this data. + /// The config used when creating this resource. Use the `r#type` to know how to parse this data. pub config: Value, - /// The data associated with this resource. Use the [Self::r#type] to know how to parse this data. + /// The data associated with this resource. Use the `r#type` to know how to parse this data. pub data: Value, } diff --git a/common/src/secrets.rs b/common/src/secrets.rs index 7ce4684b97..e90c4c7512 100644 --- a/common/src/secrets.rs +++ b/common/src/secrets.rs @@ -4,7 +4,7 @@ use zeroize::Zeroize; /// Wrapper type for secret values such as passwords or authentication keys. /// -/// Once wrapped, the inner value cannot leak accidentally, as both the [`Display`] and [`Debug`] +/// Once wrapped, the inner value cannot leak accidentally, as both the [`std::fmt::Display`] and [`Debug`] /// implementations cover up the actual value and only show the type. /// /// If you need access to the inner value, there is an [expose](`Secret::expose`) method. diff --git a/examples b/examples index 7af5b42f94..7cf399638b 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 7af5b42f944a386140df8fdfe045a12fc88657e5 +Subproject commit 7cf399638b96e7c78a06b68b0b2a5a980f7b3d32 diff --git a/resources/metadata/Cargo.toml b/resources/metadata/Cargo.toml index fbaaf4e7a4..4650539a05 100644 --- a/resources/metadata/Cargo.toml +++ b/resources/metadata/Cargo.toml @@ -8,4 +8,4 @@ keywords = ["shuttle-service", "metadata"] [dependencies] async-trait = "0.1.56" -shuttle-service = { path = "../../service", version = "0.41.0" } +shuttle-service = { path = "../../service", version = "<=0.44.0" } diff --git a/resources/metadata/README.md b/resources/metadata/README.md index 171af2863d..566d836650 100644 --- a/resources/metadata/README.md +++ b/resources/metadata/README.md @@ -1,22 +1,3 @@ # Shuttle Metadata -This plugin allows applications to obtain certain information about their runtime environment. - -## Usage - -Add `shuttle-metadata` to the dependencies for your service. - -You can get this resource using the `shuttle_metadata::ShuttleMetadata` attribute to get a `Metadata`. This struct will contain information such as the Shuttle service name. - -```rust -#[shuttle_runtime::main] -async fn app( - #[shuttle_metadata::ShuttleMetadata] metadata: shuttle_metadata::Metadata, -) -> __ { ... } -``` - -#### Example projects that use `shuttle-metadata` - -| Framework | Link | -| --------- | -------------------------------------------------------------------------------------- | -| Axum | [axum example](https://github.com/shuttle-hq/shuttle-examples/tree/main/axum/metadata) | +This plugin has been moved to [shuttle-runtime](https://crates.io/crates/shuttle-runtime). diff --git a/resources/metadata/src/lib.rs b/resources/metadata/src/lib.rs index e612e08e27..38ab9d1ede 100644 --- a/resources/metadata/src/lib.rs +++ b/resources/metadata/src/lib.rs @@ -3,6 +3,10 @@ pub use shuttle_service::{DeploymentMetadata as Metadata, Environment, SecretSto use shuttle_service::{Error, ResourceFactory, ResourceInputBuilder}; #[derive(Default)] +#[deprecated( + since = "0.42.0", + note = "This plugin has been moved to shuttle_runtime::Metadata, see https://docs.shuttle.rs/resources/shuttle-metadata" +)] pub struct ShuttleMetadata; #[async_trait] diff --git a/resources/secrets/Cargo.toml b/resources/secrets/Cargo.toml index 22223b9b4e..86b39f0040 100644 --- a/resources/secrets/Cargo.toml +++ b/resources/secrets/Cargo.toml @@ -9,4 +9,4 @@ keywords = ["shuttle-service", "secrets"] [dependencies] async-trait = "0.1.56" serde_json = "1" -shuttle-service = { path = "../../service", version = "0.41.0" } +shuttle-service = { path = "../../service", version = "<=0.44.0" } diff --git a/resources/secrets/README.md b/resources/secrets/README.md index 9164d92df6..09b60280fe 100644 --- a/resources/secrets/README.md +++ b/resources/secrets/README.md @@ -1,32 +1,3 @@ # Shuttle Secrets -This plugin manages secrets on [Shuttle](https://www.shuttle.rs). - -## Usage - -Add `shuttle-secrets` to the dependencies for your service, and add a `Secrets.toml` to the root of your project -with the secrets you'd like to store. Make sure to add `Secrets*.toml` to a `.gitignore` to omit your secrets from version control. - -Next, pass `#[shuttle_secrets::Secrets] secret_store: SecretStore` as an argument to your `shuttle_service::main` function. -`SecretStore::get` can now be called to retrieve your API keys and other secrets at runtime. - -## Example - -```rust,ignore -#[shuttle_runtime::main] -async fn rocket( - #[shuttle_secrets::Secrets] secret_store: SecretStore, -) -> ShuttleRocket { - // get secret defined in `Secrets.toml` file. - let secret = if let Some(secret) = secret_store.get("MY_API_KEY") { - secret - } else { - return Err(anyhow!("secret was not found").into()); - }; - - let state = MyState { secret }; - let rocket = rocket::build().mount("/", routes![secret]).manage(state); - - Ok(rocket.into()) -} -``` +This plugin has been moved to [shuttle-runtime](https://crates.io/crates/shuttle-runtime). diff --git a/resources/secrets/src/lib.rs b/resources/secrets/src/lib.rs index 44d3b20ddc..fb7725a643 100644 --- a/resources/secrets/src/lib.rs +++ b/resources/secrets/src/lib.rs @@ -1,3 +1,4 @@ + #![doc = include_str!("../README.md")] use async_trait::async_trait; pub use shuttle_service::SecretStore; @@ -8,6 +9,10 @@ use shuttle_service::{ /// Secrets plugin that provides service secrets #[derive(Default)] +#[deprecated( + since = "0.42.0", + note = "This plugin has been moved to shuttle_runtime::Secrets, see https://docs.shuttle.rs/resources/shuttle-secrets" +)] pub struct Secrets; #[async_trait] diff --git a/runtime/README.md b/runtime/README.md index 07cc9d24b2..f06b4d3007 100644 --- a/runtime/README.md +++ b/runtime/README.md @@ -1,15 +1,93 @@ -# shuttle-runtime +# Shuttle - Deploy Rust apps with a single Cargo subcommand -[Shuttle](https://www.shuttle.rs/) is a Rust-native cloud development platform that lets you deploy your Rust apps for free. - -Shuttle is built for productivity, reliability and performance: +
+ +
-- Zero-Configuration support for Rust using annotations -- Automatic resource provisioning (databases, caches, subdomains, etc.) via [Infrastructure-From-Code](https://www.shuttle.rs/blog/2022/05/09/ifc) -- First-class support for popular Rust frameworks ([Actix Web](https://docs.shuttle.rs/examples/actix), [Rocket](https://docs.shuttle.rs/examples/rocket), [Axum](https://docs.shuttle.rs/examples/axum), and [more](https://docs.shuttle.rs/examples/other)) -- Support for deploying Discord bots using [Serenity](https://docs.shuttle.rs/examples/serenity) -- Scalable hosting (with optional self-hosting in the future) +[Shuttle](https://www.shuttle.rs/) is a Rust-native cloud development platform that lets you deploy your Rust apps for free. 📖 Check out our documentation to get started quickly: [docs.shuttle.rs](https://docs.shuttle.rs) 🙋‍♂️ If you have any questions, join our [Discord](https://discord.gg/shuttle) server. + +## Usage + +Start by installing the [`cargo shuttle`](https://docs.rs/crate/cargo-shuttle/latest) subcommand by running the following in a terminal: + +```bash +cargo install cargo-shuttle +``` + +Now that Shuttle is installed, you can initialize a project with Axum boilerplate: + +```bash +cargo shuttle init --template axum my-axum-app +``` + +By looking at the `Cargo.toml` file of the generated `my-axum-app` project you will see it has been made to +be a binary crate with a few dependencies including `shuttle-runtime` and `shuttle-axum`. + +```toml +axum = "0.7.3" +shuttle-axum = "0.41.0" +shuttle-runtime = "0.41.0" +tokio = "1.28.2" +``` + +A boilerplate code for your axum project can also be found in `src/main.rs`: + +```rust,no_run +use axum::{routing::get, Router}; + +async fn hello_world() -> &'static str { + "Hello, world!" +} + +#[shuttle_runtime::main] +async fn main() -> shuttle_axum::ShuttleAxum { + let router = Router::new().route("/", get(hello_world)); + + Ok(router.into()) +} +``` + +Check out [our docs](https://docs.shuttle.rs/introduction/welcome) to see all the frameworks we support, or +our [examples](https://github.com/shuttle-hq/shuttle-examples) if you prefer that format. + +## Running locally + +To test your app locally before deploying, use: + +```bash +cargo shuttle run +``` + +You should see your app build and start on the default port 8000. You can test this using; + +```bash +curl http://localhost:8000/ +# Hello, world! +``` + +## Deploying + +Before you can deploy, you have to create a project. This will start a deployer container for your +project under the hood, ensuring isolation from other users' projects. PS. you don't have to do this +now if you did in in the `cargo shuttle init` flow. + +```bash +cargo shuttle project start +``` + +Then, deploy the service with: + +```bash +cargo shuttle deploy +``` + +Your service will immediately be available at `https://{project_name}.shuttleapp.rs/`. For example: + +```bash +curl https://my-axum-app.shuttleapp.rs/ +# Hello, world! +``` diff --git a/runtime/src/alpha.rs b/runtime/src/alpha.rs index 51c5938781..0675b55f50 100644 --- a/runtime/src/alpha.rs +++ b/runtime/src/alpha.rs @@ -25,9 +25,8 @@ use tokio::sync::{ use tokio_stream::wrappers::ReceiverStream; use tonic::{transport::Server, Request, Response, Status}; -use crate::__internals::print_version; - use crate::args::args; +use crate::print_version; // uses custom macro instead of clap to reduce dependency weight args! { @@ -49,17 +48,14 @@ pub async fn start(loader: impl Loader + Send + 'static, runner: impl Runner + S Ok(args) => args, Err(e) => { eprintln!("Runtime received malformed or incorrect args, {e}"); - let help_str = "[HINT]: Run shuttle with `cargo shuttle run`"; + let help_str = "[HINT]: Run your Shuttle app with `cargo shuttle run`"; let wrapper_str = "-".repeat(help_str.len()); eprintln!("{wrapper_str}\n{help_str}\n{wrapper_str}"); return; } }; - println!( - "shuttle-runtime executable started (version {})", - crate::VERSION - ); + println!("{} {} executable started", crate::NAME, crate::VERSION); // this is handled after arg parsing to not interfere with --version above #[cfg(feature = "setup-tracing")] @@ -81,21 +77,10 @@ pub async fn start(loader: impl Loader + Send + 'static, runner: impl Runner + S .init(); println!( - "{}\n\ - {}\n\ - To disable the subscriber and use your own,\n\ - turn off the default features for {}:\n\ - \n\ - {}\n\ - {}", - "=".repeat(63).yellow(), - "Shuttle's default tracing subscriber is initialized!" - .yellow() - .bold(), - "shuttle-runtime".italic(), - r#"shuttle-runtime = { version = "...", default-features = false }"#.italic(), - "=".repeat(63).yellow(), + "{}", + "Shuttle's default tracing subscriber is initialized!".yellow(), ); + println!("To disable it and use your own, check the docs: https://docs.shuttle.rs/configuration/logs"); } // where to serve the gRPC control layer diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 4ef3567a1e..8aa8b58a89 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1,212 +1,14 @@ +#![doc = include_str!("../README.md")] #![doc( html_logo_url = "https://raw.githubusercontent.com/shuttle-hq/shuttle/main/assets/logo-square-transparent.png", html_favicon_url = "https://raw.githubusercontent.com/shuttle-hq/shuttle/main/assets/favicon.ico" )] -//! # Shuttle - Deploy Rust apps with a single Cargo subcommand -//!
-//! -//!
-//! -//! Hello, and welcome to the shuttle API documentation! -//! -//! Shuttle is an open-source app platform that uses traits and annotations to configure your backend deployments. -//! -//! ## Usage -//! Start by installing the [`cargo shuttle`](https://docs.rs/crate/cargo-shuttle/latest) subcommand by running the following in a terminal: -//! -//! ```bash -//! $ cargo install cargo-shuttle -//! ``` -//! -//! Now that shuttle is installed, you can initialize a project with Axum boilerplate: -//! ```bash -//! $ cargo shuttle init --template axum my-axum-app -//! ``` -//! -//! By looking at the `Cargo.toml` file of the generated `my-axum-app` project you will see it has been made to -//! be a binary crate with a few dependencies including `shuttle-runtime` and `shuttle-axum`. -//! -//! ```toml -//! axum = "0.7.3" -//! shuttle-axum = "0.41.0" -//! shuttle-runtime = "0.41.0" -//! tokio = "1.28.2" -//! ``` -//! -//! A boilerplate code for your axum project can also be found in `src/main.rs`: -//! -//! ```rust,no_run -//! use axum::{routing::get, Router}; -//! -//! async fn hello_world() -> &'static str { -//! "Hello, world!" -//! } -//! -//! #[shuttle_runtime::main] -//! async fn main() -> shuttle_axum::ShuttleAxum { -//! let router = Router::new().route("/", get(hello_world)); -//! -//! Ok(router.into()) -//! } -//! ``` -//! -//! Check out [our docs](https://docs.shuttle.rs/introduction/welcome) to see all the frameworks we support, or -//! our [examples](https://github.com/shuttle-hq/shuttle-examples) if you prefer that format. -//! -//! ## Running locally -//! To test your app locally before deploying, use: -//! -//! ```bash -//! $ cargo shuttle run -//! ``` -//! -//! You should see your app build and start on the default port 8000. You can test this using; -//! -//! ```bash -//! $ curl http://localhost:8000/ -//! Hello, world! -//! ``` -//! -//! ## Deploying -//! -//! You can deploy your service with the [`cargo shuttle`](https://docs.rs/crate/cargo-shuttle/latest) subcommand too. -//! But, you will need to authenticate with the shuttle service first using: -//! -//! ```bash -//! $ cargo shuttle login -//! ``` -//! -//! This will open a browser window and prompt you to connect using your GitHub account. -//! -//! Before you can deploy, you have to create a project. This will start a deployer container for your -//! project under the hood, ensuring isolation from other users' projects. PS. you don't have to do this -//! now if you did in in the `cargo shuttle init` flow. -//! -//! ```bash -//! $ cargo shuttle project start -//! ``` -//! -//! Then, deploy the service with: -//! -//! ```bash -//! $ cargo shuttle deploy -//! ``` -//! -//! Your service will immediately be available at `{crate_name}.shuttleapp.rs`. For example: -//! -//! ```bash -//! $ curl https://my-axum-app.shuttleapp.rs/ -//! Hello, world! -//! ``` -//! -//! ## Using `sqlx` -//! -//! Here is a quick example to deploy a rocket service that uses a postgres database and [sqlx](http://docs.rs/sqlx): -//! -//! Initialize a project with Rocket boilerplate: -//! ```bash -//! $ cargo shuttle init --template rocket my-rocket-app -//! ``` -//! -//! Add `shuttle-shared-db` as a dependency with the `postgres` feature, and add `sqlx` as a dependency with the -//! `runtime-tokio-native-tls` and `postgres` features inside `Cargo.toml`: -//! -//! ```toml -//! shuttle-shared-db = { version = "0.41.0", features = ["postgres"] } -//! sqlx = "0.7.1" -//! ``` -//! -//! Now update the `#[shuttle_runtime::main]` function to take in a `PgPool`: -//! -//! ```rust,no_run -//! #[macro_use] -//! extern crate rocket; -//! -//! use rocket::State; -//! use sqlx::PgPool; -//! use shuttle_rocket::ShuttleRocket; -//! -//! struct MyState(PgPool); -//! -//! #[get("/")] -//! fn hello(state: &State) -> &'static str { -//! // Do things with `state.0`... -//! "Hello, Postgres!" -//! } -//! -//! #[shuttle_runtime::main] -//! async fn rocket(#[shuttle_shared_db::Postgres] pool: PgPool) -> ShuttleRocket { -//! let state = MyState(pool); -//! let rocket = rocket::build().manage(state).mount("/", routes![hello]); -//! -//! Ok(rocket.into()) -//! } -//! ``` -//! -//! For a local run, shuttle will automatically provision a Postgres instance inside a [Docker](https://www.docker.com/) container on your machine and connect it to the `PgPool`. -//! -//! For deploys, shuttle will provision a database for your application and connect it to the `PgPool` on your behalf. -//! -//! To learn more about shuttle managed resources, see our [resource docs](https://docs.shuttle.rs/resources/shuttle-shared-db). -//! -//! ## Configuration -//! -//! The `cargo shuttle` command can be customized by creating a `Shuttle.toml` in the same location as your `Cargo.toml`. -//! -//! ##### Change the name of your service -//! -//! To have your service deployed with a different name, add a `name` entry in the `Shuttle.toml`: -//! -//! ```toml -//! name = "hello-world" -//! ``` -//! -//! If the `name` key is not specified, the service's name will be the same as the crate's name. -//! -//! Alternatively, you can override the project name on the command-line, by passing the --name argument to any subcommand like so: -//! -//! ```bash -//! $ cargo shuttle deploy --name=$PROJECT_NAME -//! ``` -//! -//! ##### Using Podman instead of Docker -//! If you are using [Podman](https://podman.io/) instead of Docker, then `cargo shuttle run` will give -//! `got unexpected error while inspecting docker container: error trying to connect: No such file or directory` error. -//! -//! To fix this error you will need to expose a rootless socket for Podman first. This can be done using: -//! -//! ```bash -//! podman system service --time=0 unix:///tmp/podman.sock -//! ``` -//! -//! Now set the `DOCKER_HOST` environment variable to point to this socket using: -//! -//! ```bash -//! export DOCKER_HOST=unix:///tmp/podman.sock -//! ``` -//! -//! Now all `cargo shuttle run` commands will work against Podman. -//! -//! ## Getting API keys -//! -//! After you've installed the [cargo-shuttle](https://docs.rs/crate/cargo-shuttle/latest) command, run: -//! -//! ```bash -//! $ cargo shuttle login -//! ``` -//! -//! this will open a browser window and prompt you to connect using your GitHub account. -//! -//! ## Join Discord -//! -//! If you have any questions, [join our Discord server](https://discord.gg/shuttle). There's always someone on there that can help! -//! -//! You can also [open an issue or a discussion on GitHub](https://github.com/shuttle-hq/shuttle). // Public API pub use shuttle_codegen::main; pub use shuttle_service::{ - CustomError, DbInput, Error, IntoResource, ResourceFactory, ResourceInputBuilder, Service, + CustomError, DbInput, DeploymentMetadata, Error, IntoResource, ResourceFactory, + ResourceInputBuilder, SecretStore, Service, }; // Useful re-exports @@ -218,6 +20,9 @@ mod args; const NAME: &str = env!("CARGO_PKG_NAME"); const VERSION: &str = env!("CARGO_PKG_VERSION"); +fn print_version() { + println!("{} {}", crate::NAME, crate::VERSION); +} // Not part of public API #[doc(hidden)] @@ -233,9 +38,83 @@ pub mod __internals { pub use strfmt::strfmt; #[cfg(feature = "setup-tracing")] pub use tracing_subscriber; +} + +pub use plugins::*; +/// Built-in plugins +mod plugins { + use crate::async_trait; + use shuttle_service::{ + resource::{ProvisionResourceRequest, ShuttleResourceOutput, Type}, + DeploymentMetadata, Error, ResourceFactory, ResourceInputBuilder, SecretStore, + }; + + /// ## Shuttle Metadata + /// + /// Plugin for getting various metadata at runtime. + /// + /// ### Usage + /// + /// ```rust,ignore + /// #[shuttle_runtime::main] + /// async fn main( + /// #[shuttle_runtime::Metadata] metadata: DeploymentMetadata, + /// ) -> __ { ... } + #[derive(Default)] + pub struct Metadata; + + #[async_trait] + impl ResourceInputBuilder for Metadata { + type Input = DeploymentMetadata; + type Output = DeploymentMetadata; + + async fn build(self, factory: &ResourceFactory) -> Result { + Ok(factory.get_metadata()) + } + } + + /// ## Shuttle Secrets + /// + /// Plugin for getting secrets in your [Shuttle](https://www.shuttle.rs) service. + /// + /// ### Usage + /// + /// Add a `Secrets.toml` file to the root of your crate with the secrets you'd like to store. + /// Make sure to add `Secrets*.toml` to `.gitignore` to omit your secrets from version control. + /// + /// Next, add `#[shuttle_runtime::Secrets] secrets: SecretStore` as a parameter to your `shuttle_service::main` function. + /// `SecretStore::get` can now be called to retrieve your API keys and other secrets at runtime. + /// + /// ### Example + /// + /// ```rust,ignore + /// #[shuttle_runtime::main] + /// async fn main( + /// #[shuttle_runtime::Secrets] secrets: SecretStore + /// ) -> ShuttleAxum { + /// // get secret defined in `Secrets.toml` file. + /// let secret = secrets.get("MY_API_KEY").unwrap(); + /// + /// let router = Router::new() + /// .route("/", || async move { format!("My secret is: {}", secret) }); + /// + /// Ok(router.into()) + /// } + /// ``` + #[derive(Default)] + pub struct Secrets; + + #[async_trait] + impl ResourceInputBuilder for Secrets { + type Input = ProvisionResourceRequest; + type Output = ShuttleResourceOutput; - // Print the version of the runtime. - pub fn print_version() { - println!("{} {}", crate::NAME, crate::VERSION); + async fn build(self, _factory: &ResourceFactory) -> Result { + Ok(ProvisionResourceRequest::new( + Type::Secrets, + serde_json::Value::Null, + serde_json::Value::Null, + )) + } } } diff --git a/scripts/patches.toml b/scripts/patches.toml index 0c9bc82073..b94c85fbaf 100644 --- a/scripts/patches.toml +++ b/scripts/patches.toml @@ -6,12 +6,10 @@ shuttle-runtime = { path = "BASE/runtime" } shuttle-service = { path = "BASE/service" } shuttle-aws-rds = { path = "BASE/resources/aws-rds" } -shuttle-metadata = { path = "BASE/resources/metadata" } shuttle-opendal = { path = "BASE/resources/opendal" } shuttle-persist = { path = "BASE/resources/persist" } shuttle-qdrant = { path = "BASE/resources/qdrant" } shuttle-shared-db = { path = "BASE/resources/shared-db" } -shuttle-secrets = { path = "BASE/resources/secrets" } shuttle-turso = { path = "BASE/resources/turso" } shuttle-axum = { path = "BASE/services/shuttle-axum" } diff --git a/service/src/lib.rs b/service/src/lib.rs index b7388e450f..c9c5b673cb 100644 --- a/service/src/lib.rs +++ b/service/src/lib.rs @@ -114,7 +114,7 @@ impl IntoResource for ShuttleResource /// The core trait of the Shuttle platform. Every service deployed to Shuttle needs to implement this trait. /// -/// An `Into` implementor is what is returned in the [`shuttle_runtime::main`] macro +/// An `Into` implementor is what is returned in the `shuttle_runtime::main` macro /// in order to run it on the Shuttle servers. #[async_trait] pub trait Service: Send { diff --git a/services/shuttle-actix-web/README.md b/services/shuttle-actix-web/README.md index 9176405e44..687e0365d4 100644 --- a/services/shuttle-actix-web/README.md +++ b/services/shuttle-actix-web/README.md @@ -1,4 +1,4 @@ -## Shuttle service integration for the Actix Web framework. +## Shuttle service integration for the Actix Web framework ### Example @@ -19,5 +19,4 @@ async fn actix_web() -> ShuttleActixWeb &'static str { "Hello, world!" @@ -18,5 +16,4 @@ async fn rocket() -> shuttle_rocket::ShuttleRocket { Ok(rocket.into()) } -# } ``` diff --git a/services/shuttle-salvo/README.md b/services/shuttle-salvo/README.md index d3c81e35cb..53bae0baa6 100644 --- a/services/shuttle-salvo/README.md +++ b/services/shuttle-salvo/README.md @@ -1,4 +1,4 @@ -## Shuttle service integration for the Salvo web framework. +## Shuttle service integration for the Salvo web framework ### Example @@ -16,5 +16,4 @@ async fn salvo() -> shuttle_salvo::ShuttleSalvo { Ok(router.into()) } - ``` diff --git a/services/shuttle-serenity/Cargo.toml b/services/shuttle-serenity/Cargo.toml index bcff870496..3f2e03dce4 100644 --- a/services/shuttle-serenity/Cargo.toml +++ b/services/shuttle-serenity/Cargo.toml @@ -13,12 +13,6 @@ serenity = { version = "0.12", default-features = false, features = ["client", " serenity-0-11 = { package = "serenity", version = "0.11.7", default-features = false, features = ["client", "gateway", "model"], optional = true } shuttle-runtime = { path = "../../runtime", version = "0.41.0", default-features = false } -[dev-dependencies] -anyhow = "1.0.69" -shuttle-secrets = { path = "../../resources/secrets" } -tokio = { version = "1.26.0", features = ["macros", "rt-multi-thread"] } -tracing = "0.1.37" - [features] default = ["rustls_backend"] diff --git a/services/shuttle-serenity/README.md b/services/shuttle-serenity/README.md index 8cb362c25e..ca7cab99db 100644 --- a/services/shuttle-serenity/README.md +++ b/services/shuttle-serenity/README.md @@ -12,12 +12,12 @@ shuttle-serenity = { version = "0.41.0", default-features = false, features = [" ### Example ```rust,ignore -use anyhow::anyhow; +use anyhow::Context as _; use serenity::async_trait; use serenity::model::channel::Message; use serenity::model::gateway::Ready; use serenity::prelude::*; -use shuttle_secrets::SecretStore; +use shuttle_runtime::SecretStore; use tracing::{error, info}; struct Bot; @@ -39,14 +39,10 @@ impl EventHandler for Bot { #[shuttle_runtime::main] async fn serenity( - #[shuttle_secrets::Secrets] secret_store: SecretStore, + #[shuttle_runtime::Secrets] secrets: SecretStore, ) -> shuttle_serenity::ShuttleSerenity { // Get the discord token set in `Secrets.toml` - let token = if let Some(token) = secret_store.get("DISCORD_TOKEN") { - token - } else { - return Err(anyhow!("'DISCORD_TOKEN' was not found").into()); - }; + let token = secrets.get("DISCORD_TOKEN").context("'DISCORD_TOKEN' was not found")?; // Set gateway intents, which decides what events the bot will be notified about let intents = GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT; diff --git a/services/shuttle-thruster/README.md b/services/shuttle-thruster/README.md index 699f928a0c..344d7027f9 100644 --- a/services/shuttle-thruster/README.md +++ b/services/shuttle-thruster/README.md @@ -1,4 +1,4 @@ -## Shuttle service integration for the Thruster web framework. +## Shuttle service integration for the Thruster web framework ### Example diff --git a/services/shuttle-tide/README.md b/services/shuttle-tide/README.md index 5b443fc3f1..e4c54235c8 100644 --- a/services/shuttle-tide/README.md +++ b/services/shuttle-tide/README.md @@ -1,4 +1,4 @@ -## Shuttle service integration for the Tide web framework. +## Shuttle service integration for the Tide web framework ### Example diff --git a/services/shuttle-tower/README.md b/services/shuttle-tower/README.md index 555f6efc01..c62a600e6c 100644 --- a/services/shuttle-tower/README.md +++ b/services/shuttle-tower/README.md @@ -1,4 +1,4 @@ -## Shuttle service integration for the Tower framework. +## Shuttle service integration for the Tower framework ### Example diff --git a/services/shuttle-warp/README.md b/services/shuttle-warp/README.md index d1184ebe83..ed060a2419 100644 --- a/services/shuttle-warp/README.md +++ b/services/shuttle-warp/README.md @@ -1,4 +1,4 @@ -## Shuttle service integration for the Warp web framework. +## Shuttle service integration for the Warp web framework ### Example