plugin_run.rs 9.77 KiB
use crate::command_line_interface::CliOptions;
use crate::error::Error;
use crate::error::Result;
use crate::internal_api;
use crate::internal_api::new_random_string;
use crate::plugin_auth_crypto::DatabaseKey;
use crate::schema::Schema;
use log::info;
use rusqlite::Transaction;
use std::collections::HashMap;
use std::process::Command;
use warp::http::status::StatusCode;
/// Run a plugin, making sure that the correct ENV variables and settings are passed
/// to the containerization / deployment processes.
///
/// Internally passes to docker / kubernetes / scripts
/// depending on how Pod is configured by the user.
#[allow(clippy::too_many_arguments)]
pub fn run_plugin_container(
    tx: &Transaction,
    schema: &Schema,
    container_image: String,
    target_item_id: &str,
    triggered_by_item_id: &str,
    pod_owner: &str,
    database_key: &DatabaseKey,
    cli_options: &CliOptions,
) -> Result<()> {
    info!(
        "Trying to run plugin container for target_item_id {}",
        target_item_id
    let target_item = internal_api::get_item_tx(tx, schema, target_item_id)?;
    let target_item = target_item.into_iter().next().ok_or_else(|| Error {
        code: StatusCode::BAD_REQUEST,
        msg: format!(
            "Failed to find target item {} to run a plugin against",
            target_item_id
    })?;
    let target_item_json = serde_json::to_string(&target_item)?;
    let auth = database_key.create_plugin_auth()?;
    let auth = serde_json::to_string(&auth)?;
    let script_override = cli_options
        .insecure_plugin_script
        .iter()
        .find(|(image, _script)| image == &container_image)
        .map(|(_image, script)| script);
    if let Some(script_path) = script_override {
        run_local_script(
            &container_image,
            script_path,
            &target_item_json,
            pod_owner,
            &auth,
            triggered_by_item_id,
            cli_options,
    } else if cli_options.use_kubernetes {
        run_kubernetes_container(
            &container_image,
            &target_item_json,
            pod_owner,
            &auth,
            triggered_by_item_id,
            cli_options,
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
} else { run_docker_container( &container_image, &target_item_json, pod_owner, &auth, triggered_by_item_id, cli_options, ) } } fn run_local_script( _container: &str, plugin_path: &str, target_item: &str, pod_owner: &str, pod_auth: &str, triggered_by_item_id: &str, cli_options: &CliOptions, ) -> Result<()> { let pod_full_address = callback_address(cli_options, false); let args: Vec<String> = Vec::new(); let mut env_vars = HashMap::new(); env_vars.insert("POD_FULL_ADDRESS", pod_full_address.as_str()); env_vars.insert("POD_TARGET_ITEM", target_item); env_vars.insert("POD_PLUGINRUN_ID", triggered_by_item_id); env_vars.insert("POD_OWNER", pod_owner); env_vars.insert("POD_AUTH_JSON", pod_auth); run_any_command(plugin_path, &args, &env_vars, triggered_by_item_id) } /// Example: /// docker run \ /// --network=host \ /// --env=POD_FULL_ADDRESS="http://localhost:3030" \ /// --env=POD_TARGET_ITEM="{...json...}" \ /// --env=POD_OWNER="...64-hex-chars..." \ /// --env=POD_AUTH_JSON="{...json...}" \ /// --name="$containerImage-$trigger_item_id" \ /// --rm \ /// -- \ /// "$containerImage" fn run_docker_container( container_image: &str, target_item_json: &str, pod_owner: &str, pod_auth: &str, triggered_by_item_id: &str, cli_options: &CliOptions, ) -> Result<()> { let docker_network = match &cli_options.plugins_docker_network { Some(net) => net.to_string(), None => "host".to_string(), }; let container_id = format!( "{}-{}-{}", pod_owner .chars() .filter(|c| c.is_ascii_alphanumeric()) .collect::<String>(), container_image .chars() .filter(|c| c.is_ascii_alphanumeric()) .collect::<String>(), triggered_by_item_id .chars() .filter(|c| c.is_ascii_alphanumeric()) .collect::<String>() );