diff --git a/cloud/core/BUILD.bazel b/cloud/core/BUILD.bazel index a8934ea11..9e63110f9 100644 --- a/cloud/core/BUILD.bazel +++ b/cloud/core/BUILD.bazel @@ -29,6 +29,17 @@ aliases = { "//cloud/core/cedar": "core_cedar", } +genrule( + name = "status_extract", + srcs = [], + outs = ["status_values.txt"], + cmd = """ + grep -E '^(COMMIT_SHA|GIT_BRANCH)' bazel-out/volatile-status.txt \ + | awk '{print $$1 "=" $$2}' > $@ + """, + stamp = 1, +) + scuffle_package( srcs = glob( [ @@ -44,6 +55,7 @@ scuffle_package( "static_policies.cedarschema", ], crate_name = "scufflecloud-core", + rustc_env_files = [":status_extract"], deps = deps, ) diff --git a/cloud/core/emails/BUILD.bazel b/cloud/core/emails/BUILD.bazel index 39f73e4ce..361cfa8ee 100644 --- a/cloud/core/emails/BUILD.bazel +++ b/cloud/core/emails/BUILD.bazel @@ -18,6 +18,7 @@ scuffle_package( crate_name = "scufflecloud-core-emails-render-preview", crate_type = "bin", readme = False, + rustc_env_files = [], tags = ["manual"], deps = [":emails"], ) diff --git a/cloud/core/src/services.rs b/cloud/core/src/services.rs index 341070265..b18f261ce 100644 --- a/cloud/core/src/services.rs +++ b/cloud/core/src/services.rs @@ -3,6 +3,8 @@ use std::sync::Arc; use axum::http::{HeaderName, StatusCode}; use axum::{Extension, Json}; +use geo_ip::maxminddb; +use geo_ip::middleware::IpAddressInfo; use reqwest::header::CONTENT_TYPE; use scuffle_http::http::Method; use tinc::TincService; @@ -61,6 +63,53 @@ fn grpc_web_cors_layer() -> CorsLayer { .allow_headers(tower_http::cors::Any) } +#[derive(serde::Serialize)] +struct RootGeoResponse { + city: Option, + country_code: Option, +} + +#[derive(serde::Serialize)] +struct RootResponse { + version: &'static str, + ip_address: std::net::IpAddr, + geo_location: RootGeoResponse, + branch: Option<&'static str>, + commit: Option<&'static str>, +} + +async fn root( + Extension(global): Extension>, + Extension(ip_address_info): Extension, +) -> Json { + let geo_city = global + .geo_ip_resolver() + .lookup::(ip_address_info.ip_address) + .ok() + .flatten(); + + let city = geo_city + .as_ref() + .and_then(|c| c.city.as_ref()) + .and_then(|c| c.names.as_ref()) + .and_then(|c| c.get("en").map(|s| s.to_string())); + + let country_code = geo_city + .as_ref() + .and_then(|c| c.country.as_ref()) + .and_then(|c| c.iso_code.map(|s| s.to_string())); + + let resp = RootResponse { + version: env!("CARGO_PKG_VERSION"), + ip_address: ip_address_info.ip_address, + geo_location: RootGeoResponse { city, country_code }, + branch: option_env!("GIT_BRANCH"), + commit: option_env!("COMMIT_SHA"), + }; + + Json(resp) +} + impl scuffle_bootstrap::Service for CoreSvc { async fn run(self, global: Arc, ctx: scuffle_context::Context) -> anyhow::Result<()> { // REST @@ -125,6 +174,7 @@ impl scuffle_bootstrap::Service for CoreSvc { .layer(grpc_web_cors_layer()); let mut router = axum::Router::new() + .route("/", axum::routing::get(root::)) .nest("/v1", v1_rest_router) .merge(grpc_router) .route_layer(axum::middleware::from_fn(crate::middleware::auth::)) diff --git a/misc/utils/rust/package.bzl b/misc/utils/rust/package.bzl index d1b65b92f..1729d1eb2 100644 --- a/misc/utils/rust/package.bzl +++ b/misc/utils/rust/package.bzl @@ -35,7 +35,8 @@ def scuffle_package( target_compatible_with = None, rustc_flags = None, rustc_env = None, - nightly = None): + nightly = None, + rustc_env_files = None): """Creates a rust_library and corresponding rust_test target. Args: @@ -58,6 +59,7 @@ def scuffle_package( rustc_flags: Additional rustc flags to add to the build. rustc_env: Additional env vars to add to rustc. nightly: If we should use nightly mode. + rustc_env_files: Additional rustc env files. """ package_name = native.package_name() @@ -95,6 +97,8 @@ def scuffle_package( rustc_flags = [] if rustc_env == None: rustc_env = {} + if rustc_env_files == None: + rustc_env_files = [] NAME_MAPPINGS = { "rlib": "lib", @@ -106,6 +110,7 @@ def scuffle_package( fail("crate_type must be one of: %s" % [kind for kind in NAME_MAPPINGS.keys()]) name = package_name.split("/")[-1] if name == None else name + colon_name = ":" + name cargo_toml_env_vars( name = name + "_cargo_toml_env", @@ -116,6 +121,8 @@ def scuffle_package( visibility = ["//visibility:private"], ) + rustc_env_files += [colon_name + "_cargo_toml_env"] + extract_cargo_lints( name = name + "_cargo_toml_lints", manifest = ":Cargo.toml", @@ -130,8 +137,6 @@ def scuffle_package( "RUSTC_BOOTSTRAP": "1", } - colon_name = ":" + name - normal_deps = all_crate_deps(normal = True, package_name = package_name, features = features) + deps + ["@rules_rust//rust/runfiles"] normal_proc_macro_deps = all_crate_deps(proc_macro = True, package_name = package_name, features = features) + proc_macro_deps aliases = aliases | dep_aliases(package_name = package_name, features = features) @@ -155,7 +160,7 @@ def scuffle_package( tags = tags, rustc_flags = rustc_flags_combined, rustc_env = rustc_env, - rustc_env_files = [colon_name + "_cargo_toml_env"], + rustc_env_files = rustc_env_files, target_compatible_with = target_compatible_with, ) @@ -202,7 +207,7 @@ def scuffle_package( deps = all_test_deps, proc_macro_deps = all_test_proc_macro_deps, crate_features = features.select(), - rustc_env_files = [colon_name + "_cargo_toml_env"], + rustc_env_files = rustc_env_files, rustc_flags = rustc_flags_combined + [ "--cfg=coverage_nightly", "@$(location //settings:test_rustc_flags)", @@ -226,7 +231,7 @@ def scuffle_package( data = test_data, env = test_env, tags = test_tags, - rustc_env_files = [colon_name + "_cargo_toml_env"], + rustc_env_files = rustc_env_files, rustc_flags = rustc_flags_combined, rustc_env = rustc_env, # Needs to be marked as not testonly because the rust_clippy @@ -277,7 +282,7 @@ def scuffle_package( rustdoc( name = name + "_doc", crate = colon_name, - rustdoc_env_files = [colon_name + "_cargo_toml_env"], + rustdoc_env_files = rustc_env_files, rustdoc_flags = rustdoc_flags, visibility = visibility, target_compatible_with = target_compatible_with, @@ -287,7 +292,7 @@ def scuffle_package( name = name + "_doc_json", crate = colon_name, output_format = "json", - rustdoc_env_files = [colon_name + "_cargo_toml_env"], + rustdoc_env_files = rustc_env_files, rustdoc_flags = [ "-Zunstable-options", "--cap-lints=allow",