Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/api/actor/src/assert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ pub async fn server_for_env(
server_ids: vec![server_id],
})
.await?;
let server = unwrap_with!(servers_res.servers.first(), SERVERS_SERVER_NOT_FOUND);
let server = unwrap_with!(servers_res.servers.first(), ACTOR_NOT_FOUND);

// Validate token can access server
ensure_with!(server.env_id == env_id, SERVERS_SERVER_NOT_FOUND);
ensure_with!(server.env_id == env_id, ACTOR_NOT_FOUND);

Ok(())
}
64 changes: 53 additions & 11 deletions packages/api/actor/src/route/actors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ async fn get_inner(
server_ids: vec![actor_id],
})
.await?;
let server = unwrap_with!(servers_res.servers.first(), SERVERS_SERVER_NOT_FOUND);
let server = unwrap_with!(servers_res.servers.first(), ACTOR_NOT_FOUND);

// Get the datacenter
let dc_res = ctx
Expand All @@ -49,7 +49,7 @@ async fn get_inner(
let dc = unwrap!(dc_res.datacenters.first());

// Validate token can access server
ensure_with!(server.env_id == env_id, SERVERS_SERVER_NOT_FOUND);
ensure_with!(server.env_id == env_id, ACTOR_NOT_FOUND);

Ok(models::ActorGetActorResponse {
actor: Box::new(ds::types::convert_actor_to_api(server.clone(), dc)?),
Expand Down Expand Up @@ -119,7 +119,12 @@ pub async fn create(
name_ids: vec![body.region.clone()],
})
.await?;
let datacenter_id = unwrap!(resolved_dc_ids.datacenters.first()).datacenter_id;
let datacenter_id = unwrap_with!(
resolved_dc_ids.datacenters.first(),
ACTOR_FAILED_TO_CREATE,
error = "Region not found."
)
.datacenter_id;

let tags = unwrap_with!(
serde_json::from_value(body.tags.unwrap_or_default()).ok(),
Expand Down Expand Up @@ -163,8 +168,8 @@ pub async fn create(
.ports
.unwrap_or_default()
.into_iter()
.map(|(s, p)| Ok((
s,
.map(|(s, p)| GlobalResult::Ok((
s.clone(),
ds::workflows::server::Port {
internal_port: p.internal_port.map(TryInto::try_into).transpose()?,
routing: if let Some(routing) = p.routing {
Expand Down Expand Up @@ -193,10 +198,22 @@ pub async fn create(
guard: None,
host: Some(_),
} => ds::types::Routing::Host {
protocol: p.protocol.api_try_into()?,
protocol: match p.protocol.api_try_into() {
Err(err) if GlobalError::is(&err, formatted_error::code::ACTOR_FAILED_TO_CREATE) => {
// Add location
bail_with!(
ACTOR_FAILED_TO_CREATE,
error = format!("network.ports[{s:?}].protocol: Host port protocol must be either TCP or UDP.")
);
}
x => x?,
},
},
models::ActorPortRouting { .. } => {
bail_with!(SERVERS_MUST_SPECIFY_ROUTING_TYPE)
bail_with!(
ACTOR_FAILED_TO_CREATE,
error = format!("network.ports[{s:?}].routing: Must specify either `game_guard` or `host` routing type.")
);
}
}
} else {
Expand All @@ -217,8 +234,8 @@ pub async fn create(
tokio::select! {
res = ready_sub.next() => { res?; },
res = fail_sub.next() => {
res?;
bail_with!(SERVERS_SERVER_FAILED_TO_CREATE);
let msg = res?;
bail_with!(ACTOR_FAILED_TO_CREATE, error = msg.message);
}
}

Expand All @@ -227,7 +244,7 @@ pub async fn create(
server_ids: vec![server_id],
})
.await?;
let server = unwrap_with!(servers_res.servers.first(), SERVERS_SERVER_NOT_FOUND);
let server = unwrap_with!(servers_res.servers.first(), ACTOR_NOT_FOUND);

let dc_res = ctx
.op(cluster::ops::datacenter::get::Input {
Expand Down Expand Up @@ -622,10 +639,35 @@ async fn resolve_build_id(
(Some(build_id), None) => Ok(build_id),
// Resolve build from tags
(None, Some(build_tags)) => {
let build_tags = serde_json::from_value::<HashMap<String, String>>(build_tags)?;

ensure_with!(
build_tags.len() < 64,
ACTOR_FAILED_TO_CREATE,
error = "Too many build tags (max 64)."
);

for (k, v) in &build_tags {
ensure_with!(
k.len() < 128,
ACTOR_FAILED_TO_CREATE,
error = format!(
"build_tags[{:?}]: Build tag label too large (max 128 bytes).",
&k[..128]
)
);
ensure_with!(
v.len() < 256,
ACTOR_FAILED_TO_CREATE,
error =
format!("build_tags[{k:?}]: Build tag value too large (max 256 bytes).")
);
}

let builds_res = ctx
.op(build::ops::resolve_for_tags::Input {
env_id,
tags: serde_json::from_value(build_tags)?,
tags: build_tags,
})
.await?;

Expand Down
58 changes: 6 additions & 52 deletions packages/api/actor/src/route/builds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ pub async fn patch_tags(
let tags = unwrap_with!(body.tags, API_BAD_BODY, error = "missing field `tags`");
let tags = serde_json::from_value(tags).map_err(|err| err_code!(API_BAD_BODY, error = err))?;

ensure_with!(
tags.as_object().map(|x| x.len()).unwrap_or_default() <= 64,
ACTOR_BUILD_INVALID_PATCH_CONFIG,
error = "Too many tags (max 64)."
);

let build_res = ctx
.op(build::ops::get::Input {
build_ids: vec![build_id],
Expand Down Expand Up @@ -294,39 +300,6 @@ pub async fn create_build(
.await?;
let cluster_id = unwrap!(cluster_res.games.first()).cluster_id;

let prewarm_datacenter_ids = if let Some(prewarm_datacenter_slugs) = body.prewarm_regions {
// Resolve datacenter slugs
ctx.op(cluster::ops::datacenter::resolve_for_name_id::Input {
cluster_id,
name_ids: prewarm_datacenter_slugs,
})
.await?
.datacenters
.into_iter()
.map(|dc| dc.datacenter_id)
.collect::<Vec<_>>()
} else {
// Prewarm all datacenters
let cluster_dcs_res = ctx
.op(cluster::ops::datacenter::list::Input {
cluster_ids: vec![cluster_id],
})
.await?;

unwrap!(cluster_dcs_res.clusters.first())
.datacenter_ids
.clone()
};

// Prewarm build
if !prewarm_datacenter_ids.is_empty() {
ctx.op(build::ops::prewarm_ats::Input {
datacenter_ids: prewarm_datacenter_ids,
build_ids: vec![create_res.build_id],
})
.await?;
}

Ok(models::ActorPrepareBuildResponse {
build: create_res.build_id,
presigned_requests: create_res
Expand All @@ -343,23 +316,6 @@ pub async fn create_build_deprecated(
env_id: Uuid,
body: models::ServersCreateBuildRequest,
) -> GlobalResult<models::ServersCreateBuildResponse> {
let prewarm_regions = if let Some(prewarm_datacenters) = body.prewarm_datacenters {
let dc_res = ctx
.op(cluster::ops::datacenter::get::Input {
datacenter_ids: prewarm_datacenters,
})
.await?;
let prewarm_regions = dc_res
.datacenters
.iter()
.map(|dc| dc.name_id.clone())
.collect::<Vec<_>>();

Some(prewarm_regions)
} else {
None
};

let global = build_global_query_compat(&ctx, game_id, env_id).await?;
let build_res = create_build(
ctx,
Expand All @@ -376,8 +332,6 @@ pub async fn create_build_deprecated(
}),
multipart_upload: body.multipart_upload,
name: body.name,
tags: None,
prewarm_regions,
},
global,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
name = "ACTOR_BUILD_INVALID_CONFIG"
description = "Invalid build config: {error}."
http_status = 400
---

# Actor Build Invalid Config

The config provided to create a build was invalid.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
name = "ACTOR_BUILD_INVALID_PATCH_CONFIG"
description = "Invalid build patch config: {error}."
http_status = 400
---

# Actor Build Invalid Patch Config

The config provided to patch a build was invalid.
10 changes: 10 additions & 0 deletions packages/common/formatted-error/errors/actor/failed_to_create.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
name = "ACTOR_FAILED_TO_CREATE"
description = "Invalid actor configuration: {error}."
description_basic = "Actor failed to create."
http_status = 400
---

# Actor Failed To Create

Actor failed to create.
9 changes: 9 additions & 0 deletions packages/common/formatted-error/errors/actor/not_found.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
name = "ACTOR_NOT_FOUND"
description = "Actor not found."
http_status = 400
---

# Actor Not Found

Actor not found for the given ID.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading