orcs 0.0.8

Microservices monorepo orchestration tool
Documentation
use crate::store::{get_store, Store};
use crate::Error;
use crate::Project;
use crate::Service;
use crate::StageContext;
use clap::ArgMatches;
use std::fs::File;
use std::io::prelude::*;
use std::sync::Arc;
use tracing::{debug, instrument};

#[instrument(skip(subcommand))]
pub fn get(project_path: &str, subcommand: &ArgMatches) -> Result<(), Error> {
    debug!("Retrieve parameter value");
    // Load the project
    let project = Project::from_path(project_path)?;

    // Retrieve the param name
    let param_name = subcommand.value_of("name").unwrap();

    // Global parameter
    if !param_name.contains(':') {
        if let Some(context) = StageContext::from_env() {
            let stage = project
                .stages
                .get(&context.stage)
                .expect("stage missing in project file");
            if let Some(value) = stage.params.get(param_name) {
                print!("{}", value);
                return Ok(());
            }
        }

        // TODO: Environment parameters

        if let Some(global) = &project.global {
            if let Some(value) = global.params.get(param_name) {
                print!("{}", value);
                return Ok(());
            }
        }
    }

    if !can_get(project.clone(), param_name) {
        return Err(Error::GetParameterError(
            "permission denied to get the parameter",
            param_name.to_string(),
        ));
    }

    // Load the data store
    let store = get_store(project)?;

    // Print the item
    print!("{}", store.get(param_name)?);

    Ok(())
}

#[instrument(skip(subcommand))]
pub fn get_file(project_path: &str, subcommand: &ArgMatches) -> Result<(), Error> {
    debug!("Retrieve parameter value file");
    // Load the project
    let project = Project::from_path(project_path)?;

    // Retrieve the param name
    let param_name = subcommand.value_of("name").unwrap();
    let filename = subcommand.value_of("filename").unwrap();

    if !can_get(project.clone(), param_name) {
        return Err(Error::GetParameterError(
            "permission denied to get the parameter",
            param_name.to_string(),
        ));
    }

    // Load the data store
    let store = get_store(project)?;

    // Print the parameter value in binary
    let data = store.get_bytes(param_name)?;

    let mut file = File::create(filename)?;
    file.write_all(&data)?;

    Ok(())
}

fn can_get(project: Arc<Project>, param_name: &str) -> bool {
    // This is a global/stage/environment parameter, and not a file parameter
    if !param_name.contains(':') {
        return true;
    }

    let dep_name = param_name.split(':').collect::<Vec<&str>>()[0];

    // Always allow outside of a stage context
    let context = match StageContext::from_env() {
        Some(context) => context,
        None => return true,
    };

    // Only allow if the current service depends on the service providing the
    // parameter.
    let service = Service::from_name(project, &context.service).unwrap();
    let deps = service.depends_on(&context.stage);

    deps.contains(&dep_name.to_string())
}