Skip to content

Commit

Permalink
refactor: move secrets and metadata plugins to runtime (#1673)
Browse files Browse the repository at this point in the history
* refactor: move secrets and metadata plugins to runtime

* feat: impl config::Source for SecretStore

* ci: skip crates

* fix lock

* Revert "feat: impl config::Source for SecretStore"

This reverts commit 7442c24.

* fix docs

* fix: deprecation warnings

* bump examples

* fix

* fix serenity

* nit

* bump examples

* fix serenity

* fix rocket doc test

* bump examples

* bump examples
  • Loading branch information
jonaro00 authored Mar 15, 2024
1 parent b40a14b commit f15e6bb
Show file tree
Hide file tree
Showing 28 changed files with 211 additions and 326 deletions.
2 changes: 0 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion cargo-shuttle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,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."
Expand Down
2 changes: 1 addition & 1 deletion codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) |
Expand Down
4 changes: 2 additions & 2 deletions common/src/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down
2 changes: 1 addition & 1 deletion common/src/secrets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion examples
Submodule examples updated 50 files
+8 −25 .github/workflows/ci.yml
+23 −8 _scripts/check-templates.rs
+0 −1 actix-web/clerk/backend/Cargo.toml
+2 −2 actix-web/clerk/backend/src/main.rs
+1 −2 axum/hello-world/Cargo.toml
+0 −1 axum/metadata/Cargo.toml
+2 −2 axum/metadata/src/main.rs
+2 −0 axum/oauth2/.gitignore
+22 −0 axum/oauth2/Cargo.toml
+18 −0 axum/oauth2/README.md
+3 −0 axum/oauth2/migrations/20230815100114_schema.down.sql
+15 −0 axum/oauth2/migrations/20230815100114_schema.up.sql
+93 −0 axum/oauth2/src/main.rs
+46 −0 axum/oauth2/src/routes/errors.rs
+2 −0 axum/oauth2/src/routes/mod.rs
+114 −0 axum/oauth2/src/routes/oauth.rs
+5 −0 bevy/hello-world/.gitignore
+3 −0 bevy/hello-world/Cargo.toml
+5 −0 bevy/hello-world/Makefile
+20 −0 bevy/hello-world/README.md
+1 −0 bevy/hello-world/Shuttle.toml
+ bevy/hello-world/dist/Roboto-Black.ttf
+31 −0 bevy/hello-world/dist/index.html
+7 −0 bevy/hello-world/game/Cargo.toml
+50 −0 bevy/hello-world/game/src/main.rs
+11 −0 bevy/hello-world/server/Cargo.toml
+11 −0 bevy/hello-world/server/src/main.rs
+2 −0 ci.sh
+0 −1 fullstack-templates/saas/backend/Cargo.toml
+2 −2 fullstack-templates/saas/backend/src/main.rs
+6 −9 loco/hello-world/Cargo.toml
+3 −3 loco/hello-world/src/bin/shuttle.rs
+0 −1 other/standalone-binary/Cargo.toml
+2 −2 other/standalone-binary/src/bin/shuttle.rs
+0 −1 poise/hello-world/Cargo.toml
+2 −2 poise/hello-world/src/main.rs
+2 −1 rocket/jwt-authentication/src/claims.rs
+0 −1 rocket/secrets/Cargo.toml
+1 −1 rocket/secrets/Secrets.toml.example
+4 −8 rocket/secrets/src/main.rs
+0 −1 serenity/hello-world/Cargo.toml
+4 −8 serenity/hello-world/src/main.rs
+0 −1 serenity/postgres/Cargo.toml
+2 −2 serenity/postgres/src/main.rs
+15 −0 serenity/weather-forecast/Cargo.toml
+3 −0 serenity/weather-forecast/README.md
+3 −0 serenity/weather-forecast/Secrets.toml
+131 −0 serenity/weather-forecast/src/main.rs
+88 −0 serenity/weather-forecast/src/weather.rs
+133 −110 templates.toml
2 changes: 1 addition & 1 deletion resources/metadata/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
21 changes: 1 addition & 20 deletions resources/metadata/README.md
Original file line number Diff line number Diff line change
@@ -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).
4 changes: 4 additions & 0 deletions resources/metadata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion resources/secrets/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
31 changes: 1 addition & 30 deletions resources/secrets/README.md
Original file line number Diff line number Diff line change
@@ -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).
5 changes: 5 additions & 0 deletions resources/secrets/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

#![doc = include_str!("../README.md")]
use async_trait::async_trait;
pub use shuttle_service::SecretStore;
Expand All @@ -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]
Expand Down
96 changes: 87 additions & 9 deletions runtime/README.md
Original file line number Diff line number Diff line change
@@ -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:
<div style="display: flex; margin-top: 30px; margin-bottom: 30px;">
<img src="https://raw.githubusercontent.com/shuttle-hq/shuttle/main/assets/logo-rectangle-transparent.png" width="400px" style="margin-left: auto; margin-right: auto;"/>
</div>

- 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!
```
27 changes: 6 additions & 21 deletions runtime/src/alpha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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! {
Expand All @@ -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")]
Expand All @@ -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
Expand Down
Loading

0 comments on commit f15e6bb

Please sign in to comment.