diff --git a/errors/game/env-not-found.md b/errors/game/env-not-found.md new file mode 100644 index 0000000000..c2b99770c5 --- /dev/null +++ b/errors/game/env-not-found.md @@ -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. diff --git a/proto/backend/ds.proto b/proto/backend/ds.proto index 72fcfbb238..e72790b705 100644 --- a/proto/backend/ds.proto +++ b/proto/backend/ds.proto @@ -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 tags = 5; diff --git a/svc/Cargo.lock b/svc/Cargo.lock index 2b7824faac..53ef8f0c90 100644 --- a/svc/Cargo.lock +++ b/svc/Cargo.lock @@ -800,7 +800,7 @@ dependencies = [ "build", "build-create", "build-get", - "build-list-for-game", + "build-list-for-env", "cdn-namespace-domain-create", "chirp-client", "chrono", @@ -812,7 +812,7 @@ dependencies = [ "ds-server-create", "ds-server-delete", "ds-server-get", - "ds-server-list-for-game", + "ds-server-list-for-env", "faker-build", "faker-game", "faker-game-namespace", @@ -1616,6 +1616,7 @@ dependencies = [ "faker-game", "faker-user", "game-get", + "game-namespace-get", "prost 0.10.4", "reqwest 0.11.27", "rivet-operation", @@ -1662,6 +1663,19 @@ dependencies = [ "sqlx 0.7.4 (git+https://github.com/rivet-gg/sqlx?rev=08d6e61aa0572e7ec557abbedb72cebb96e1ac5b)", ] +[[package]] +name = "build-list-for-env" +version = "0.0.1" +dependencies = [ + "chirp-client", + "chirp-worker", + "faker-build", + "faker-game", + "prost 0.10.4", + "rivet-operation", + "sqlx 0.7.4 (git+https://github.com/rivet-gg/sqlx?rev=08d6e61aa0572e7ec557abbedb72cebb96e1ac5b)", +] + [[package]] name = "build-list-for-game" version = "0.0.1" @@ -3136,7 +3150,7 @@ dependencies = [ ] [[package]] -name = "ds-server-list-for-game" +name = "ds-server-list-for-env" version = "0.0.1" dependencies = [ "chirp-client", diff --git a/svc/Cargo.toml b/svc/Cargo.toml index 765ab6139d..845eb4eebb 100644 --- a/svc/Cargo.toml +++ b/svc/Cargo.toml @@ -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", diff --git a/svc/api/servers/Cargo.toml b/svc/api/servers/Cargo.toml index 22160dbbe6..4d22b4fe24 100644 --- a/svc/api/servers/Cargo.toml +++ b/svc/api/servers/Cargo.toml @@ -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" } diff --git a/svc/api/servers/src/auth.rs b/svc/api/servers/src/auth.rs index 634f0a6a53..3e6ee95f2b 100644 --- a/svc/api/servers/src/auth.rs +++ b/svc/api/servers/src/auth.rs @@ -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, diff --git a/svc/api/servers/src/route/builds.rs b/svc/api/servers/src/route/builds.rs index ef3ef80146..025201c66e 100644 --- a/svc/api/servers/src/route/builds.rs +++ b/svc/api/servers/src/route/builds.rs @@ -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, game_id: Uuid, + env_id: Uuid, build_id: Uuid, _watch_index: WatchIndexQuery, ) -> GlobalResult { - 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 @@ -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, @@ -58,13 +65,16 @@ pub struct GetQuery { pub async fn list( ctx: Ctx, game_id: Uuid, + env_id: Uuid, _watch_index: WatchIndexQuery, query: GetQuery, ) -> GlobalResult { - 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?; @@ -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, game_id: Uuid, + env_id: Uuid, build_id: Uuid, body: models::ServersPatchBuildTagsRequest, ) -> GlobalResult { - 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 = serde_json::from_value::>(unwrap!(body.tags))?; @@ -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, game_id: Uuid, + env_id: Uuid, body: models::ServersCreateBuildRequest, ) -> GlobalResult { - 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 @@ -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()?), @@ -220,10 +236,13 @@ pub async fn create_build( pub async fn complete_build( ctx: Ctx, game_id: Uuid, + env_id: Uuid, build_id: Uuid, _body: serde_json::Value, ) -> GlobalResult { - 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()], @@ -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 ); diff --git a/svc/api/servers/src/route/logs.rs b/svc/api/servers/src/route/logs.rs index a99956c5e5..c17281cc5b 100644 --- a/svc/api/servers/src/route/logs.rs +++ b/svc/api/servers/src/route/logs.rs @@ -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, @@ -19,11 +19,14 @@ pub struct GetServerLogsQuery { pub async fn get_logs( ctx: Ctx, game_id: Uuid, + env_id: Uuid, server_id: Uuid, watch_index: WatchIndexQuery, query: GetServerLogsQuery, ) -> GlobalResult { - 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?; diff --git a/svc/api/servers/src/route/mod.rs b/svc/api/servers/src/route/mod.rs index fd8f5a49cd..ebdebc05dd 100644 --- a/svc/api/servers/src/route/mod.rs +++ b/svc/api/servers/src/route/mod.rs @@ -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, ), @@ -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), }, }, diff --git a/svc/api/servers/src/route/servers.rs b/svc/api/servers/src/route/servers.rs index 40e5f1d33d..29056ddf09 100644 --- a/svc/api/servers/src/route/servers.rs +++ b/svc/api/servers/src/route/servers.rs @@ -8,14 +8,17 @@ use std::collections::HashMap; use crate::{assert, auth::Auth}; -// MARK: GET /games/{}/servers/{} +// MARK: GET /games/{}/environments/{}/servers/{} pub async fn get( ctx: Ctx, game_id: Uuid, + env_id: Uuid, server_id: Uuid, _watch_index: WatchIndexQuery, ) -> GlobalResult { - ctx.auth().check_game(ctx.op_ctx(), game_id, true).await?; + ctx.auth() + .check_game(ctx.op_ctx(), game_id, env_id, true) + .await?; // Get the server let get_res = op!([ctx] ds_server_get { @@ -26,7 +29,7 @@ pub async fn get( // Validate token can access server ensure_with!( - unwrap!(server.game_id).as_uuid() == game_id, + unwrap!(server.env_id).as_uuid() == env_id && unwrap!(server.env_id).as_uuid() == env_id, SERVERS_SERVER_NOT_FOUND ); @@ -35,21 +38,23 @@ pub async fn get( }) } -// MARK: POST /games/{}/servers +// MARK: POST /games/{}/environments/{}/servers pub async fn create( ctx: Ctx, game_id: Uuid, + env_id: Uuid, body: models::ServersCreateServerRequest, ) -> GlobalResult { - 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 games = ctx + let clusters_get = ctx .op(cluster::ops::get_for_game::Input { game_ids: vec![game_id], }) - .await? - .games; - let cluster_id = unwrap!(games.first()).cluster_id; + .await?; + let cluster_id = unwrap!(clusters_get.games.first()).cluster_id; let datacenters = ctx .op(cluster::ops::datacenter::list::Input { @@ -68,7 +73,7 @@ pub async fn create( tracing::info!(?tags, "creating server with tags"); let server = op!([ctx] ds_server_create { - game_id: Some(game_id.into()), + env_id: Some(env_id.into()), datacenter_id: Some(body.datacenter.into()), cluster_id: Some(cluster_id.into()), tags: tags, @@ -121,7 +126,7 @@ pub async fn create( }) } -// MARK: DELETE /games/{}/servers/{} +// MARK: DELETE /games/{}/environments/{}/servers/{} #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DeleteQuery { override_kill_timeout: Option, @@ -130,10 +135,13 @@ pub struct DeleteQuery { pub async fn destroy( ctx: Ctx, game_id: Uuid, + env_id: Uuid, server_id: Uuid, query: DeleteQuery, ) -> GlobalResult { - ctx.auth().check_game(ctx.op_ctx(), game_id, true).await?; + ctx.auth() + .check_game(ctx.op_ctx(), game_id, env_id, true) + .await?; assert::server_for_game(&ctx, server_id, game_id).await?; @@ -146,7 +154,7 @@ pub async fn destroy( Ok(serde_json::json!({})) } -// MARK: GET /games/{}/servers +// MARK: GET /games/{}/environments/{}/servers #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ListQuery { tags_json: Option, @@ -155,10 +163,13 @@ pub struct ListQuery { pub async fn list_servers( ctx: Ctx, game_id: Uuid, + env_id: Uuid, _watch_index: WatchIndexQuery, query: ListQuery, ) -> GlobalResult { - 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] ds_server_list_for_game { game_id: Some(game_id.into()), diff --git a/svc/pkg/build/db/build/migrations/20240812204859_env_owner.down.sql b/svc/pkg/build/db/build/migrations/20240812204859_env_owner.down.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/svc/pkg/build/db/build/migrations/20240812204859_env_owner.up.sql b/svc/pkg/build/db/build/migrations/20240812204859_env_owner.up.sql new file mode 100644 index 0000000000..e13c6cf517 --- /dev/null +++ b/svc/pkg/build/db/build/migrations/20240812204859_env_owner.up.sql @@ -0,0 +1,3 @@ +ALTER TABLE builds ALTER COLUMN game_id DROP NOT NULL; +ALTER TABLE builds ADD env_id UUID; + diff --git a/svc/pkg/build/ops/create/Cargo.toml b/svc/pkg/build/ops/create/Cargo.toml index a5c41bac03..a87daaa25f 100644 --- a/svc/pkg/build/ops/create/Cargo.toml +++ b/svc/pkg/build/ops/create/Cargo.toml @@ -12,6 +12,7 @@ prost = "0.10" util-build = { package = "rivet-util-build", path = "../../util" } game-get = { path = "../../../game/ops/get" } +game-namespace-get = { path = "../../../game/ops/namespace-get" } upload-prepare = { path = "../../../upload/ops/prepare" } [dependencies.sqlx] diff --git a/svc/pkg/build/ops/create/src/lib.rs b/svc/pkg/build/ops/create/src/lib.rs index 9cca98250b..a50b14c43b 100644 --- a/svc/pkg/build/ops/create/src/lib.rs +++ b/svc/pkg/build/ops/create/src/lib.rs @@ -10,19 +10,30 @@ async fn handle( let kind = unwrap!(backend::build::BuildKind::from_i32(ctx.kind)); let compression = unwrap!(backend::build::BuildCompression::from_i32(ctx.compression)); - let game_id = **unwrap_ref!(ctx.game_id); + let game_id = ctx.game_id.map(|x| x.as_uuid()); + let env_id = ctx.env_id.map(|x| x.as_uuid()); ensure!( util::check::display_name_long(&ctx.display_name), "invalid display name" ); // Validate game exists - let game_res = op!([ctx] game_get { - game_ids: vec![game_id.into()], - }) - .await?; - let game = game_res.games.first(); - ensure!(game.is_some(), "game not found"); + if let Some(game_id) = game_id { + let game_res = op!([ctx] game_get { + game_ids: vec![game_id.into()], + }) + .await?; + let game = game_res.games.first(); + ensure!(game.is_some(), "game not found"); + } + if let Some(env_id) = env_id { + let env_res = op!([ctx] game_namespace_get { + namespace_ids: vec![env_id.into()], + }) + .await?; + let env = env_res.namespaces.first(); + ensure!(env.is_some(), "game not found"); + } let (image_tag, upload_id, image_presigned_requests) = if let Some(build_kind) = &ctx.default_build_kind { @@ -102,6 +113,7 @@ async fn handle( db_build.builds ( build_id, game_id, + env_id, upload_id, display_name, image_tag, @@ -114,6 +126,7 @@ async fn handle( ", build_id, game_id, + env_id, upload_id, &ctx.display_name, image_tag, diff --git a/svc/pkg/build/ops/list-for-env/Cargo.toml b/svc/pkg/build/ops/list-for-env/Cargo.toml new file mode 100644 index 0000000000..7a51d78b3d --- /dev/null +++ b/svc/pkg/build/ops/list-for-env/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "build-list-for-env" +version = "0.0.1" +edition = "2021" +authors = ["Rivet Gaming, LLC "] +license = "Apache-2.0" + +[dependencies] +rivet-operation = { path = "../../../../../lib/operation/core" } +chirp-client = { path = "../../../../../lib/chirp/client" } +prost = "0.10" + +[dependencies.sqlx] +git = "https://github.com/rivet-gg/sqlx" +rev = "08d6e61aa0572e7ec557abbedb72cebb96e1ac5b" +default-features = false + +[dev-dependencies] +chirp-worker = { path = "../../../../../lib/chirp/worker" } + +faker-build = { path = "../../../faker/ops/build" } +faker-game = { path = "../../../faker/ops/game" } diff --git a/svc/pkg/build/ops/list-for-env/README.md b/svc/pkg/build/ops/list-for-env/README.md new file mode 100644 index 0000000000..8a60907ed7 --- /dev/null +++ b/svc/pkg/build/ops/list-for-env/README.md @@ -0,0 +1 @@ +# build-list-for-game diff --git a/svc/pkg/build/ops/list-for-env/Service.toml b/svc/pkg/build/ops/list-for-env/Service.toml new file mode 100644 index 0000000000..6f3f3e8bd5 --- /dev/null +++ b/svc/pkg/build/ops/list-for-env/Service.toml @@ -0,0 +1,10 @@ +[service] +name = "build-list-for-env" + +[runtime] +kind = "rust" + +[operation] + +[databases] +db-build = {} diff --git a/svc/pkg/build/ops/list-for-env/src/lib.rs b/svc/pkg/build/ops/list-for-env/src/lib.rs new file mode 100644 index 0000000000..04908e7cad --- /dev/null +++ b/svc/pkg/build/ops/list-for-env/src/lib.rs @@ -0,0 +1,31 @@ +use proto::backend::pkg::*; +use rivet_operation::prelude::*; + +#[operation(name = "build-list-for-env")] +async fn handle( + ctx: OperationContext, +) -> GlobalResult { + let env_id = unwrap_ref!(ctx.env_id).as_uuid(); + + let build_ids = sql_fetch_all!( + [ctx, (Uuid,)] + " + SELECT + build_id + FROM + db_build.builds + WHERE + env_id = $1 + AND + tags @> $2 + ", + env_id, + serde_json::to_value(&ctx.tags)? + ) + .await? + .into_iter() + .map(|(id,)| common::Uuid::from(id)) + .collect::>(); + + Ok(build::list_for_env::Response { build_ids }) +} diff --git a/svc/pkg/build/proto/create.proto b/svc/pkg/build/proto/create.proto index ecef100dbd..5fd7e58272 100644 --- a/svc/pkg/build/proto/create.proto +++ b/svc/pkg/build/proto/create.proto @@ -7,7 +7,8 @@ import "proto/backend/upload.proto"; import "proto/backend/build.proto"; message Request { - rivet.common.Uuid game_id = 1; + optional rivet.common.Uuid game_id = 1; + optional rivet.common.Uuid env_id = 10; string display_name = 2; optional string image_tag = 4; optional rivet.backend.upload.PrepareFile image_file = 3; diff --git a/svc/pkg/build/proto/list-for-env.proto b/svc/pkg/build/proto/list-for-env.proto new file mode 100644 index 0000000000..7a9e8098b0 --- /dev/null +++ b/svc/pkg/build/proto/list-for-env.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +package rivet.backend.pkg.build.list_for_env; + +import "proto/common.proto"; + +message Request { + rivet.common.Uuid env_id = 1; + map tags = 2; // JSON +} + +message Response { + repeated rivet.common.Uuid build_ids = 1; +} diff --git a/svc/pkg/build/src/ops/get.rs b/svc/pkg/build/src/ops/get.rs index 2640354827..b1d23a29d6 100644 --- a/svc/pkg/build/src/ops/get.rs +++ b/svc/pkg/build/src/ops/get.rs @@ -17,7 +17,8 @@ pub struct Output { #[derive(sqlx::FromRow)] struct BuildRow { build_id: Uuid, - game_id: Uuid, + game_id: Option, + env_id: Option, upload_id: Uuid, display_name: String, image_tag: String, @@ -34,6 +35,7 @@ impl TryInto for BuildRow { Ok(types::Build { build_id: self.build_id, game_id: self.game_id, + env_id: self.env_id, upload_id: self.upload_id, display_name: self.display_name, image_tag: self.image_tag, @@ -55,6 +57,7 @@ pub async fn get(ctx: &OperationCtx, input: &Input) -> GlobalResult { SELECT build_id, game_id, + env_id, upload_id, display_name, image_tag, diff --git a/svc/pkg/build/src/types.rs b/svc/pkg/build/src/types.rs index 8b0325448c..dbe37e97e7 100644 --- a/svc/pkg/build/src/types.rs +++ b/svc/pkg/build/src/types.rs @@ -17,7 +17,8 @@ pub enum BuildCompression { #[derive(Debug)] pub struct Build { pub build_id: Uuid, - pub game_id: Uuid, + pub game_id: Option, + pub env_id: Option, pub upload_id: Uuid, pub display_name: String, pub image_tag: String, diff --git a/svc/pkg/ds/db/servers/migrations/20240501133910_init.up.sql b/svc/pkg/ds/db/servers/migrations/20240501133910_init.up.sql index cb512075ed..33ad23aadd 100644 --- a/svc/pkg/ds/db/servers/migrations/20240501133910_init.up.sql +++ b/svc/pkg/ds/db/servers/migrations/20240501133910_init.up.sql @@ -1,6 +1,6 @@ CREATE TABLE servers ( server_id UUID PRIMARY KEY, - game_id UUID NOT NULL, + env_id UUID NOT NULL, datacenter_id UUID NOT NULL, -- The server will be locked to a certain cluster, but a game might change -- clusters, and therefore the server will be moved to a new cluster. @@ -26,7 +26,7 @@ CREATE TABLE servers ( -- This is a map environment JSONB NOT NULL, - INDEX (game_id) + INDEX (env_id) ); diff --git a/svc/pkg/ds/ops/server-create/src/lib.rs b/svc/pkg/ds/ops/server-create/src/lib.rs index 2d1a2d33e9..2cc441cd7e 100644 --- a/svc/pkg/ds/ops/server-create/src/lib.rs +++ b/svc/pkg/ds/ops/server-create/src/lib.rs @@ -123,7 +123,7 @@ pub async fn handle( ) -> GlobalResult { let resources = unwrap_ref!(ctx.resources).clone(); let server_id = Uuid::new_v4(); - let game_id = unwrap_ref!(ctx.game_id).as_uuid(); + let env_id = unwrap_ref!(ctx.env_id).as_uuid(); let cluster_id = unwrap_ref!(ctx.cluster_id).as_uuid(); let datacenter_id = unwrap_ref!(ctx.datacenter_id).as_uuid(); @@ -185,7 +185,7 @@ pub async fn handle( INSERT INTO db_dynamic_servers.servers ( server_id, - game_id, + env_id, datacenter_id, cluster_id, tags, @@ -239,7 +239,7 @@ pub async fn handle( 1 ", server_id, - game_id, + env_id, datacenter_id, cluster_id, serde_json::value::to_raw_value(&ctx.tags.to_owned())?.to_string(), // 5 @@ -1389,7 +1389,7 @@ pub async fn handle( Ok(dynamic_servers::server_create::Response { server: Some(backend::ds::Server { server_id: Some(server_id.into()), - game_id: Some(game_id.into()), + env_id: Some(env_id.into()), datacenter_id: Some(datacenter_id.into()), cluster_id: Some(cluster_id.into()), tags: ctx.tags.clone(), diff --git a/svc/pkg/ds/ops/server-get/src/lib.rs b/svc/pkg/ds/ops/server-get/src/lib.rs index cb58dd162c..336d3b48ce 100644 --- a/svc/pkg/ds/ops/server-get/src/lib.rs +++ b/svc/pkg/ds/ops/server-get/src/lib.rs @@ -6,7 +6,7 @@ use std::collections::HashMap; #[derive(sqlx::FromRow)] struct Server { server_id: Uuid, - game_id: Uuid, + env_id: Uuid, datacenter_id: Uuid, cluster_id: Uuid, tags: serde_json::Value, @@ -75,7 +75,7 @@ pub async fn handle( " SELECT server_id, - game_id, + env_id, datacenter_id, cluster_id, tags, @@ -207,7 +207,7 @@ pub async fn handle( let server_proto = backend::ds::Server { server_id: Some(server.server_id.into()), - game_id: Some(server.game_id.into()), + env_id: Some(server.env_id.into()), datacenter_id: Some(server.datacenter_id.into()), cluster_id: Some(server.cluster_id.into()), tags, diff --git a/svc/pkg/ds/ops/server-list-for-game/Cargo.toml b/svc/pkg/ds/ops/server-list-for-env/Cargo.toml similarity index 94% rename from svc/pkg/ds/ops/server-list-for-game/Cargo.toml rename to svc/pkg/ds/ops/server-list-for-env/Cargo.toml index ffc8038c71..9096df4030 100644 --- a/svc/pkg/ds/ops/server-list-for-game/Cargo.toml +++ b/svc/pkg/ds/ops/server-list-for-env/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "ds-server-list-for-game" +name = "ds-server-list-for-env" version = "0.0.1" edition = "2021" authors = ["Rivet Gaming, LLC "] diff --git a/svc/pkg/ds/ops/server-list-for-game/Service.toml b/svc/pkg/ds/ops/server-list-for-env/Service.toml similarity index 59% rename from svc/pkg/ds/ops/server-list-for-game/Service.toml rename to svc/pkg/ds/ops/server-list-for-env/Service.toml index 011905a347..52677f16cf 100644 --- a/svc/pkg/ds/ops/server-list-for-game/Service.toml +++ b/svc/pkg/ds/ops/server-list-for-env/Service.toml @@ -1,5 +1,5 @@ [service] -name = "ds-server-list-for-game" +name = "ds-server-list-for-env" [runtime] kind = "rust" diff --git a/svc/pkg/ds/ops/server-list-for-game/src/lib.rs b/svc/pkg/ds/ops/server-list-for-env/src/lib.rs similarity index 88% rename from svc/pkg/ds/ops/server-list-for-game/src/lib.rs rename to svc/pkg/ds/ops/server-list-for-env/src/lib.rs index 14d0062d7c..a783806cdb 100644 --- a/svc/pkg/ds/ops/server-list-for-game/src/lib.rs +++ b/svc/pkg/ds/ops/server-list-for-env/src/lib.rs @@ -5,7 +5,7 @@ use rivet_operation::prelude::*; async fn handle( ctx: OperationContext, ) -> GlobalResult { - let game_id = unwrap_ref!(ctx.game_id).as_uuid(); + let env_id = unwrap_ref!(ctx.env_id).as_uuid(); let server_ids = sql_fetch_all!( [ctx, (Uuid,)] @@ -15,11 +15,11 @@ async fn handle( FROM db_dynamic_servers.servers WHERE - game_id = $1 + env_id = $1 AND tags @> $2 ", - game_id, + env_id, serde_json::to_value(&ctx.tags)? ) .await? diff --git a/svc/pkg/ds/ops/server-list-for-game/tests/integration.rs b/svc/pkg/ds/ops/server-list-for-env/tests/integration.rs similarity index 100% rename from svc/pkg/ds/ops/server-list-for-game/tests/integration.rs rename to svc/pkg/ds/ops/server-list-for-env/tests/integration.rs diff --git a/svc/pkg/ds/proto/server-create.proto b/svc/pkg/ds/proto/server-create.proto index b3497ad531..bd91a9d7fa 100644 --- a/svc/pkg/ds/proto/server-create.proto +++ b/svc/pkg/ds/proto/server-create.proto @@ -8,7 +8,7 @@ import "proto/backend/ds.proto"; message Request { reserved 8; - rivet.common.Uuid game_id = 1; + rivet.common.Uuid env_id = 1; rivet.common.Uuid datacenter_id = 2; rivet.common.Uuid cluster_id = 3; map tags = 5; diff --git a/svc/pkg/ds/proto/server-list-for-game.proto b/svc/pkg/ds/proto/server-list-for-env.proto similarity index 68% rename from svc/pkg/ds/proto/server-list-for-game.proto rename to svc/pkg/ds/proto/server-list-for-env.proto index 70568e6848..69f4e07551 100644 --- a/svc/pkg/ds/proto/server-list-for-game.proto +++ b/svc/pkg/ds/proto/server-list-for-env.proto @@ -1,12 +1,12 @@ syntax = "proto3"; -package rivet.backend.pkg.dynamic_servers.server_list_for_game; +package rivet.backend.pkg.dynamic_servers.server_list_for_env; import "proto/common.proto"; import "proto/backend/ds.proto"; message Request { - rivet.common.Uuid game_id = 1; + rivet.common.Uuid env_id = 1; map tags = 2; // JSON }