Skip to content

Commit

Permalink
Merge pull request #37 from wcm-io-devops/feature/use-service-propert…
Browse files Browse the repository at this point in the history
…y-in-env-vars-patching

Respect service type in environment and pipeline variable patching, add dry run
  • Loading branch information
tobias-richter authored Oct 15, 2024
2 parents fe75b22 + 2af667c commit 149f662
Show file tree
Hide file tree
Showing 5 changed files with 272 additions and 72 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,12 @@ pippo -c <pippo.json> -p <program-id> -e <environment-id> log save --service <sv
pippo -c <pippo.json> -p <program-id> -e <environment-id> log tail --service <svc> --log <log>
```

### dry-run mode

You can pass the flag `--dry-run` on the command line to preview the changes for
* environment variables
* pipeline variables

### CI mode

Since updating running pipelines or environments that are currently updating is not possible pippo will normally wait until it is possible.
Expand Down
40 changes: 37 additions & 3 deletions src/clap_app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ use crate::client::CloudManagerClient;
use crate::config::CloudManagerConfig;
use crate::encryption::{decrypt, encrypt};
use crate::logs::{download_log, tail_log};
use crate::models::{Domain, LogType, ServiceType};
use crate::models::{
Domain, EnvironmentVariableServiceType, LogType, PipelineVariableServiceType, ServiceType,
};
use crate::variables::{
get_env_vars, get_pipeline_vars, set_env_vars_from_file, set_pipeline_vars_from_file,
};
Expand Down Expand Up @@ -71,7 +73,8 @@ pub async fn init_cli() {
"🚀 Patching environment variables from input file {}\n",
input
);
set_env_vars_from_file(input, &mut cm_client, cli.ci_mode).await;
set_env_vars_from_file(input, &mut cm_client, cli.ci_mode, cli.dry_run_mode)
.await;
process::exit(0);
}
}
Expand All @@ -94,6 +97,17 @@ pub async fn init_cli() {
.await
.unwrap();
println!("{}", serde_json::to_string_pretty(&env_vars).unwrap());
if let Some(vf) = env_vars.variables.iter().find(|vf| {
vf.service == EnvironmentVariableServiceType::Invalid
}) {
eprintln!(
"{:>8} {} '{}: {}'",
"⚠".yellow(),
"WARN, invalid service type detected for variable".yellow(),
vf.name,
vf.service
);
}
}
} else {
eprintln!("❌ You have to provide a valid Cloud Manager environment ID to run this command!");
Expand Down Expand Up @@ -206,7 +220,13 @@ pub async fn init_cli() {
{
if let PipelineVarsCommands::Set { input } = &pipeline_vars_command {
println!("🚀 Patching pipeline variables from input file {}\n", input);
set_pipeline_vars_from_file(input, &mut cm_client, cli.ci_mode).await;
set_pipeline_vars_from_file(
input,
&mut cm_client,
cli.ci_mode,
cli.dry_run_mode,
)
.await;
process::exit(0);
}
}
Expand Down Expand Up @@ -276,10 +296,24 @@ pub async fn init_cli() {
get_pipeline_vars(&mut cm_client, program_id, &pipeline_id)
.await
.unwrap();

println!(
"{}",
serde_json::to_string_pretty(&pipeline_vars).unwrap()
);
if let Some(vf) = pipeline_vars
.variables
.iter()
.find(|vf| vf.service == PipelineVariableServiceType::Invalid)
{
eprintln!(
"{:>8} {} '{}: {}'",
"⚠".yellow(),
"WARN, invalid service type detected for variable".yellow(),
vf.name,
vf.service
);
}
}
} else {
eprintln!("❌ You have to provide a valid Cloud Manager pipeline ID to run this command!");
Expand Down
4 changes: 4 additions & 0 deletions src/clap_models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ pub struct Cli {
#[clap(long = "ci", global = true, action = ArgAction::SetTrue )]
pub ci_mode: bool,

/// Only log but to not apply any changes
#[clap(long = "dry-run", global = true, action = ArgAction::SetTrue )]
pub dry_run_mode: bool,

#[clap(subcommand)]
pub command: Option<Commands>,
}
Expand Down
120 changes: 105 additions & 15 deletions src/models.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
use std::fmt;
use strum_macros::{EnumString, IntoStaticStr};

// Common models used across multiple modules
Expand Down Expand Up @@ -30,37 +31,113 @@ pub struct DomainConfig {
#[derive(Debug, Deserialize, Serialize)]
pub struct EnvironmentsConfig {
pub id: u32,
pub variables: Vec<Variable>,
pub variables: Vec<EnvironmentVariable>,
pub domains: Option<Vec<DomainConfig>>,
}

/// Model for a pipeline's ID and all its variables that will be read from the configuration YAML
#[derive(Debug, Deserialize, Serialize)]
pub struct PipelinesConfig {
pub id: u32,
pub variables: Vec<Variable>,
pub variables: Vec<PipelineVariable>,
}

/// Model for common cloud manager variables

/// Possible types that a variable can have
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum VariableType {
String,
SecretString,
}

/// Model for all information about a Cloud Manager environment variable
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Variable {
pub struct EnvironmentVariable {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<String>,
#[serde(rename(deserialize = "type", serialize = "type"))]
pub variable_type: VariableType,
#[serde(skip_serializing_if = "Option::is_none")]
pub service: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(
default = "EnvironmentVariableServiceType::default",
skip_serializing_if = "environment_variable_skip_serializing"
)]
pub service: EnvironmentVariableServiceType,
}

/// Possible types that a variable can have
/// Possible service types that an environment variable can have
#[derive(Clone, Debug, Deserialize, Serialize, IntoStaticStr, EnumString, PartialEq, Eq)]
#[strum(serialize_all = "lowercase")]
#[serde(rename_all = "lowercase")]
pub enum EnvironmentVariableServiceType {
All,
Author,
Publish,
Preview,
#[serde(other)]
Invalid,
}

impl fmt::Display for EnvironmentVariableServiceType {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(
formatter,
"{}",
format!("{}", serde_json::to_string(self).unwrap().to_string())
)
}
}
fn environment_variable_skip_serializing(t: &EnvironmentVariableServiceType) -> bool {
*t == EnvironmentVariableServiceType::All
}

impl EnvironmentVariableServiceType {
fn default() -> Self {
EnvironmentVariableServiceType::All
}
}

/// Model for all information about a Cloud Manager pipeline variable
/// Model for all information about a Cloud Manager environment variable
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PipelineVariable {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<String>,
#[serde(rename(deserialize = "type", serialize = "type"))]
pub variable_type: VariableType,
#[serde(default = "PipelineVariableServiceType::default")]
pub service: PipelineVariableServiceType,
}

/// Possible service types that an pipeline variable can have
#[derive(Clone, Debug, Deserialize, Serialize, IntoStaticStr, EnumString, PartialEq, Eq)]
#[strum(serialize_all = "camelCase")]
#[serde(rename_all = "camelCase")]
pub enum VariableType {
String,
SecretString,
pub enum PipelineVariableServiceType {
Build,
UiTest,
FunctionalTest,
#[serde(other)]
Invalid,
}

impl fmt::Display for PipelineVariableServiceType {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(
formatter,
"{}",
format!("{}", serde_json::to_string(self).unwrap().to_string())
)
}
}

impl PipelineVariableServiceType {
fn default() -> Self {
PipelineVariableServiceType::Build
}
}

/// Model for the necessary JWT claims to retrieve an Adobe access token
Expand Down Expand Up @@ -139,15 +216,28 @@ pub struct Environment {

/// Struct to serialize the response of requesting /api/program/{id}/environment/{id}/variables
#[derive(Debug, Deserialize, Serialize)]
pub struct VariablesResponse {
pub struct EnvironmentVariablesResponse {
#[serde(rename(deserialize = "_embedded", serialize = "_embedded"))]
pub variables_list: EnvironmentVariablesList,
}

/// Struct to serialize the response of requesting /api/program/{id}/environment/{id}/variables
#[derive(Debug, Deserialize, Serialize)]
pub struct PipelineVariablesResponse {
#[serde(rename(deserialize = "_embedded", serialize = "_embedded"))]
pub variables_list: VariablesList,
pub variables_list: PipelineVariablesList,
}

/// Struct that holds a list of variables
#[derive(Debug, Deserialize, Serialize)]
pub struct EnvironmentVariablesList {
pub variables: Vec<EnvironmentVariable>,
}

/// Struct that holds a list of variables
#[derive(Debug, Deserialize, Serialize)]
pub struct VariablesList {
pub variables: Vec<Variable>,
pub struct PipelineVariablesList {
pub variables: Vec<PipelineVariable>,
}

// Models for representing Cloud Manager pipelines and descendant objects
Expand Down
Loading

0 comments on commit 149f662

Please sign in to comment.