Skip to content

Commit

Permalink
chore: migrate servers to use envs (#1053)
Browse files Browse the repository at this point in the history
<!-- Please make sure there is an issue that this PR is correlated to. -->

## Changes

<!-- If there are frontend changes, please include screenshots. -->
  • Loading branch information
NathanFlurry committed Aug 13, 2024
1 parent f6126f6 commit 6b50e9e
Show file tree
Hide file tree
Showing 31 changed files with 243 additions and 72 deletions.
9 changes: 9 additions & 0 deletions errors/game/env-not-found.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
name = "GAME_ENVIRONMENT_NOT_FOUND"
description = "Environment not found."
http_status = 400
---

# Environment Not Found

The requested environment was not found.
2 changes: 1 addition & 1 deletion proto/backend/ds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ message Server {
reserved 8;

rivet.common.Uuid server_id = 1;
rivet.common.Uuid game_id = 2;
rivet.common.Uuid env_id = 2;
rivet.common.Uuid datacenter_id = 3;
rivet.common.Uuid cluster_id = 4;
map<string, string> tags = 5;
Expand Down
20 changes: 17 additions & 3 deletions svc/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion svc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ members = [
"pkg/ds/ops/server-create",
"pkg/ds/ops/server-delete",
"pkg/ds/ops/server-get",
"pkg/ds/ops/server-list-for-game",
"pkg/ds/ops/server-list-for-env",
"pkg/ds/worker",
"pkg/email-verification/ops/complete",
"pkg/email-verification/ops/create",
Expand Down
4 changes: 2 additions & 2 deletions svc/api/servers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ uuid = { version = "1", features = ["v4"] }

build-create = { path = "../../pkg/build/ops/create" }
build-get = { path = "../../pkg/build/ops/get" }
build-list-for-game = { path = "../../pkg/build/ops/list-for-game" }
build-list-for-env = { path = "../../pkg/build/ops/list-for-env" }
cluster = { path = "../../pkg/cluster" }
build = { path = "../../pkg/build" }
ds-log-read = { path = "../../pkg/ds-log/ops/read" }
ds-server-create = { path = "../../pkg/ds/ops/server-create" }
ds-server-delete = { path = "../../pkg/ds/ops/server-delete" }
ds-server-get = { path = "../../pkg/ds/ops/server-get" }
ds-server-list-for-game = { path = "../../pkg/ds/ops/server-list-for-game" }
ds-server-list-for-env = { path = "../../pkg/ds/ops/server-list-for-env" }
game-get = { path = "../../pkg/game/ops/get" }
game-namespace-get = { path = "../../pkg/game/ops/namespace-get" }
game-version-get = { path = "../../pkg/game/ops/version-get" }
Expand Down
15 changes: 15 additions & 0 deletions svc/api/servers/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,25 @@ impl Auth {
&self,
ctx: &OperationContext<()>,
game_id: Uuid,
env_id: Uuid,
allow_service: bool,
) -> GlobalResult<()> {
let claims = self.claims()?;

// Get the game this env belongs to
let ns_res = op!([ctx] game_namespace_get {
namespace_ids: vec![env_id.into()],
})
.await?;
let env = unwrap!(ns_res.namespaces.first(), GAME_ENVIRONMENT_NOT_FOUND);

// Ensure belongs to game
ensure_with!(
unwrap!(env.game_id).as_uuid() == game_id,
GAME_ENVIRONMENT_NOT_FOUND
);

// Validate token
if let Ok(cloud_ent) = claims.as_game_cloud() {
ensure_with!(
cloud_ent.game_id == game_id,
Expand Down
47 changes: 33 additions & 14 deletions svc/api/servers/src/route/builds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,27 @@ use util::timestamp;

use crate::auth::Auth;

// MARK: GET /games/{}/builds/{}
// MARK: GET /games/{}/environments/{}/builds/{}
pub async fn get(
ctx: Ctx<Auth>,
game_id: Uuid,
env_id: Uuid,
build_id: Uuid,
_watch_index: WatchIndexQuery,
) -> GlobalResult<models::ServersGetBuildResponse> {
ctx.auth().check_game(ctx.op_ctx(), game_id, true).await?;
ctx.auth()
.check_game(ctx.op_ctx(), game_id, env_id, true)
.await?;

let builds_res = op!([ctx] build_get {
build_ids: vec![build_id.into()],
})
.await?;
let build = unwrap!(builds_res.builds.first());
let build = unwrap!(builds_res.builds.first(), BUILDS_BUILD_NOT_FOUND);
ensure_with!(
unwrap!(build.env_id).as_uuid() == env_id,
BUILDS_BUILD_NOT_FOUND
);

let uploads_res = op!([ctx] upload_get {
upload_ids: builds_res
Expand All @@ -49,7 +56,7 @@ pub async fn get(
})
}

// MARK: GET /games/{}/builds
// MARK: GET /games/{}/environments/{}/builds
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetQuery {
tags_json: Option<String>,
Expand All @@ -58,13 +65,16 @@ pub struct GetQuery {
pub async fn list(
ctx: Ctx<Auth>,
game_id: Uuid,
env_id: Uuid,
_watch_index: WatchIndexQuery,
query: GetQuery,
) -> GlobalResult<models::ServersListBuildsResponse> {
ctx.auth().check_game(ctx.op_ctx(), game_id, true).await?;
ctx.auth()
.check_game(ctx.op_ctx(), game_id, env_id, true)
.await?;

let list_res = op!([ctx] build_list_for_game {
game_id: Some(game_id.into()),
let list_res = op!([ctx] build_list_for_env {
env_id: Some(env_id.into()),
tags: query.tags_json.as_deref().map_or(Ok(HashMap::new()), serde_json::from_str)?,
})
.await?;
Expand Down Expand Up @@ -121,14 +131,17 @@ pub async fn list(
})
}

// MARK: PATCH /games/{}/builds/{}/tags
// MARK: PATCH /games/{}/environments/{}/builds/{}/tags
pub async fn patch_tags(
ctx: Ctx<Auth>,
game_id: Uuid,
env_id: Uuid,
build_id: Uuid,
body: models::ServersPatchBuildTagsRequest,
) -> GlobalResult<serde_json::Value> {
ctx.auth().check_game(ctx.op_ctx(), game_id, false).await?;
ctx.auth()
.check_game(ctx.op_ctx(), game_id, env_id, false)
.await?;

let tags: HashMap<String, String> =
serde_json::from_value::<HashMap<String, String>>(unwrap!(body.tags))?;
Expand All @@ -148,13 +161,16 @@ pub async fn patch_tags(
Ok(json!({}))
}

// MARK: POST /games/{}/builds/prepare
// MARK: POST /games/{}/environments/{}/builds/prepare
pub async fn create_build(
ctx: Ctx<Auth>,
game_id: Uuid,
env_id: Uuid,
body: models::ServersCreateBuildRequest,
) -> GlobalResult<models::ServersCreateBuildResponse> {
ctx.auth().check_game(ctx.op_ctx(), game_id, false).await?;
ctx.auth()
.check_game(ctx.op_ctx(), game_id, env_id, false)
.await?;

// TODO: Read and validate image file

Expand All @@ -175,7 +191,7 @@ pub async fn create_build(
};

let create_res = op!([ctx] build_create {
game_id: Some(game_id.into()),
env_id: Some(env_id.into()),
display_name: body.name,
image_tag: Some(body.image_tag),
image_file: Some((*body.image_file).api_try_into()?),
Expand Down Expand Up @@ -220,10 +236,13 @@ pub async fn create_build(
pub async fn complete_build(
ctx: Ctx<Auth>,
game_id: Uuid,
env_id: Uuid,
build_id: Uuid,
_body: serde_json::Value,
) -> GlobalResult<serde_json::Value> {
ctx.auth().check_game(ctx.op_ctx(), game_id, false).await?;
ctx.auth()
.check_game(ctx.op_ctx(), game_id, env_id, false)
.await?;

let build_res = op!([ctx] build_get {
build_ids: vec![build_id.into()],
Expand All @@ -232,7 +251,7 @@ pub async fn complete_build(
let build = unwrap_with!(build_res.builds.first(), BUILDS_BUILD_NOT_FOUND);

ensure_with!(
unwrap!(build.game_id).as_uuid() == game_id,
unwrap!(build.env_id).as_uuid() == env_id,
BUILDS_BUILD_NOT_FOUND
);

Expand Down
7 changes: 5 additions & 2 deletions svc/api/servers/src/route/logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::time::Duration;

use crate::{assert, auth::Auth};

// MARK: GET /games/{}/servers/{}/logs
// MARK: GET /games/{}/environments/{}/servers/{}/logs
#[derive(Debug, Deserialize)]
pub struct GetServerLogsQuery {
pub stream: models::CloudGamesLogStream,
Expand All @@ -19,11 +19,14 @@ pub struct GetServerLogsQuery {
pub async fn get_logs(
ctx: Ctx<Auth>,
game_id: Uuid,
env_id: Uuid,
server_id: Uuid,
watch_index: WatchIndexQuery,
query: GetServerLogsQuery,
) -> GlobalResult<models::ServersGetServerLogsResponse> {
ctx.auth().check_game(ctx.op_ctx(), game_id, false).await?;
ctx.auth()
.check_game(ctx.op_ctx(), game_id, env_id, false)
.await?;

// Validate server belongs to game
assert::server_for_game(&ctx, server_id, game_id).await?;
Expand Down
16 changes: 8 additions & 8 deletions svc/api/servers/src/route/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub async fn handle(
define_router! {
cors: CorsConfigBuilder::hub().build(),
routes: {
"games" / Uuid / "servers": {
"games" / Uuid / "environments" / Uuid / "servers": {
GET: servers::list_servers(
query: servers::ListQuery,
),
Expand All @@ -32,38 +32,38 @@ define_router! {
),
},

"games" / Uuid / "servers" / Uuid: {
"games" / Uuid / "environments" / Uuid / "servers" / Uuid: {
GET: servers::get(),
DELETE: servers::destroy(
query: servers::DeleteQuery,
),
},

"games" / Uuid / "servers" / Uuid / "logs" : {
"games" / Uuid / "environments" / Uuid / "servers" / Uuid / "logs" : {
GET: logs::get_logs(
query: logs::GetServerLogsQuery,
),
},

"games" / Uuid / "builds": {
"games" / Uuid / "environments" / Uuid / "builds": {
GET: builds::list(
query: builds::GetQuery,
),
},

"games" / Uuid / "builds" / Uuid: {
"games" / Uuid / "environments" / Uuid / "builds" / Uuid: {
GET: builds::get(),
},

"games" / Uuid / "builds" / Uuid / "tags": {
"games" / Uuid / "environments" / Uuid / "builds" / Uuid / "tags": {
PATCH: builds::patch_tags(body: models::ServersPatchBuildTagsRequest),
},

"games" / Uuid / "builds" / "prepare": {
"games" / Uuid / "environments" / Uuid / "builds" / "prepare": {
POST: builds::create_build(body: models::ServersCreateBuildRequest),
},

"games" / Uuid / "builds" / Uuid / "complete": {
"games" / Uuid / "environments" / Uuid / "builds" / Uuid / "complete": {
POST: builds::complete_build(body: serde_json::Value),
},
},
Expand Down
Loading

0 comments on commit 6b50e9e

Please sign in to comment.