mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-03 17:08:13 +00:00
145 lines
5.4 KiB
Rust
145 lines
5.4 KiB
Rust
use std::path::Path;
|
|
|
|
use log::{info, warn};
|
|
|
|
use errors::{anyhow, AnyhowResult};
|
|
use server_environment::ServerEnvironment;
|
|
|
|
pub struct BootstrapArgs<'a, P: AsRef<Path>> {
|
|
/// The name of the application or service
|
|
pub app_name: &'a str,
|
|
|
|
/// Default rust log level.
|
|
/// If the RUST_LOG env var is set, it will take precedence over this setting.
|
|
pub default_logging_override: Option<&'a str>,
|
|
|
|
/// Where to look for env conf files.
|
|
pub config_search_directories: &'a [P],
|
|
|
|
/// If true, ignore the root '.env' file.
|
|
/// TODO(bt,2025-01-23): Make this the default behavior, then remove reading from '.env' entirely,
|
|
/// There are too many apps that share this file.
|
|
pub ignore_legacy_dot_env_file: bool,
|
|
}
|
|
|
|
/// Information about how the application is deployed.
|
|
#[derive(Clone)]
|
|
pub struct ContainerEnvironment {
|
|
/// Whether the app is running in development or production.
|
|
/// Set with the env var `SERVER_ENVIRONMENT`.
|
|
pub server_environment: ServerEnvironment,
|
|
|
|
/// The worker hostname, using OS hostname detection.
|
|
/// If not determined, it will be set to the synthetic
|
|
/// value `{app_name}-unknown`.
|
|
pub hostname: String,
|
|
|
|
/// The kubernetes cluster name.
|
|
/// Set with the env var `K8S_CLUSTER_NAME`.
|
|
pub cluster_name: String,
|
|
|
|
/// Whether the container is operating on-premises.
|
|
/// False by default. Should be false if the container is
|
|
/// deployed to the cloud or run locally in development.
|
|
/// Should only be true for "data centers" we operate.
|
|
/// Set with the env var `IS_ON_PREM`.
|
|
pub is_on_prem: bool,
|
|
}
|
|
|
|
/// Environment variable for server environment.
|
|
const SERVER_ENVIRONMENT : &str = "SERVER_ENVIRONMENT";
|
|
|
|
pub fn bootstrap<P: AsRef<Path>>(args: BootstrapArgs<'_, P>) -> AnyhowResult<ContainerEnvironment> {
|
|
if args.ignore_legacy_dot_env_file {
|
|
easyenv::init_env_logger(args.default_logging_override);
|
|
} else {
|
|
easyenv::init_all_with_default_logging(args.default_logging_override);
|
|
}
|
|
|
|
info!("Bootstrapping application {}", &args.app_name);
|
|
|
|
let server_environment = easyenv::get_env_string_optional(SERVER_ENVIRONMENT)
|
|
.map(|environment| ServerEnvironment::from_str(&environment)
|
|
.ok_or(anyhow!("couldn't parse environment: {:?}", &environment)))
|
|
.transpose()?
|
|
.unwrap_or(ServerEnvironment::Development);
|
|
|
|
info!("Currently deployed in environment: {:?}",&server_environment);
|
|
|
|
// TODO(bt, 2023-04-29): There was an old note in `inference-job` about setting special k8s
|
|
// variables so we can debug on-prem workers? Something gets conflated maybe and makes it hard
|
|
// to determine which on-prem worker generates the result? Not a big priority until we have
|
|
// on-prem workloads again.
|
|
let server_hostname = hostname::get()
|
|
.ok()
|
|
.and_then(|h| h.into_string().ok())
|
|
.unwrap_or_else(|| format!("{}-unknown", args.app_name));
|
|
|
|
info!("With hostname: {:?}", &server_hostname);
|
|
|
|
let cluster_name = easyenv::get_env_string_optional("K8S_CLUSTER_NAME")
|
|
.unwrap_or("unknown-cluster".to_string());
|
|
|
|
info!("With cluster name: {:?}", &cluster_name);
|
|
|
|
// TODO(bt, 2023-04-29): These were old variables in `inference-job` that probably never got used,
|
|
// but adding these is a good idea for tracking which jobs are assigned where.
|
|
// NB: These are non-standard env vars we're injecting ourselves.
|
|
// let k8s_node_name = easyenv::get_env_string_optional("K8S_NODE_NAME");
|
|
// let k8s_pod_name = easyenv::get_env_string_optional("K8S_POD_NAME");
|
|
|
|
// NB: It'll be worthwhile to see how much compute is happening at our local on-premises cluster
|
|
// Only our local workers will set this to true.
|
|
let is_on_prem = easyenv::get_env_bool_or_default("IS_ON_PREM", false);
|
|
|
|
info!("Is on premises? {}", is_on_prem);
|
|
|
|
// TODO(bt, 2023-04-29): Determine if we want the "debug worker" flag, or if we'd rather
|
|
// have a "passive" flag + job routing system.
|
|
// Debug workers only process special debug requests. They're silent otherwise.
|
|
// Non-debug workers ignore debug requests. This is so we can deploy special code
|
|
// to debug nodes (typically just one, perhaps even ephemerally).
|
|
//let is_debug_worker = easyenv::get_env_bool_or_default("IS_DEBUG_WORKER", false);
|
|
//info!("Is debug worker? {}", is_debug_worker);
|
|
|
|
load_env_config_files(server_environment, &args)?;
|
|
|
|
Ok(ContainerEnvironment {
|
|
server_environment,
|
|
hostname: server_hostname,
|
|
cluster_name,
|
|
is_on_prem,
|
|
})
|
|
}
|
|
|
|
fn load_env_config_files<P: AsRef<Path>>(server_environment: ServerEnvironment, args: &BootstrapArgs<'_, P>) -> AnyhowResult<()> {
|
|
|
|
let env_config_file_names = match server_environment {
|
|
ServerEnvironment::Development => vec![
|
|
format!("{}.common.env", &args.app_name),
|
|
format!("{}.development.env", &args.app_name),
|
|
format!("{}.development-secrets.env", &args.app_name), // NB: .gitignore these files
|
|
],
|
|
ServerEnvironment::Production => vec![
|
|
format!("{}.common.env", &args.app_name),
|
|
format!("{}.production.env", &args.app_name),
|
|
],
|
|
};
|
|
|
|
for env_config_file in env_config_file_names.into_iter() {
|
|
info!("Loading environment variable config file: {}", &env_config_file);
|
|
|
|
let was_read = easyenv::maybe_read_env_config_from_filename_and_paths(
|
|
&env_config_file,
|
|
args.config_search_directories)?;
|
|
|
|
if was_read {
|
|
info!("Environment config file `{}` was read.", &env_config_file);
|
|
} else {
|
|
warn!("Could not read environment config file: `{}`", &env_config_file);
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|