Skip to content

Commit

Permalink
Merge pull request #14 from barnsnake351/master
Browse files Browse the repository at this point in the history
Add support for params via yaml file
  • Loading branch information
jimmycuadra authored Mar 21, 2017
2 parents 9f08f74 + c0965ec commit c43cdea
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 7 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ FLAGS:
OPTIONS:
-b, --base64-parameter <NAME> <VALUE>
Same as --parameter, but for values already encoded in Base64
-f, --param-file <FILENAME>...
Supplies a Yaml file defining any named parameters
-p, --parameter <NAME> <VALUE>
Supplies a value for the named parameter
-s, --secret <NAME> <NAMESPACE>
Expand All @@ -33,13 +35,23 @@ ARGS:
Run `ktmpl TEMPLATE` where TEMPLATE is a path to a Kubernetes manifest template in YAML format.
The included [example.yml](example.yml) is a working example template.

To provide values for template parameters, use the `--parameter` option to supply key-value pairs.
To provide values for template parameters, use either the `--parameter` or the `--parameter-file` option to supply key-value pairs.
Using the `--parameter` option:

Using the provided example.yml, this would mean:

``` bash
ktmpl example.yml --parameter MONGODB_PASSWORD secret
```

Using the `--parameter-file` option:

```
ktmpl example.yml --parameter-file params.yaml
```

If the same parameter is defined more than once, the last defined value will be used. Passing parameters on the command line `--parameter` will override any that are defined via the `--parameter-file` construct

Template parameters that have default values can be overridden with the same mechanism:

``` bash
Expand Down
5 changes: 5 additions & 0 deletions params.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
MONGODB_PASSWORD: secret
MONGODB_USER: bar
REPLICA_COUNT: 2

83 changes: 82 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,18 @@ extern crate yaml_rust as yaml;

pub use template::Template;
pub use parameter::{ParameterValue, ParameterValues};
pub use parameterfile::{ParameterFile};
pub use secret::{Secret, Secrets};

mod parameter;
mod parameterfile;
mod processor;
mod secret;
mod template;

#[cfg(test)]
mod tests {
use super::{ParameterValue, ParameterValues, Secret, Secrets, Template};
use super::{ParameterValue, ParameterValues, ParameterFile, Secret, Secrets, Template};

#[test]
fn encode_secrets() {
Expand Down Expand Up @@ -193,4 +195,83 @@ parameters:

assert!(template.process().is_err());
}

#[test]
fn parse_parameter_file() {
let parameter_file_contents = r#"
---
db_user: bob
db_password: changeme
db_port: 1234
"#;
let template_contents = r#"
---
kind: Template
apiVersion: v1
metadata:
name: param-file-example
objects:
- kind: Pod
apiVersion: v1
metadata:
name: db_app
spec:
containers:
- name: mydb
image: mydb
env:
- name: USERNAME
value: $(db_user)
- name: PASSWORD
value: $(db_password)
- name: DB_PORT
value: $(db_port)
parameters:
- name: db_user
description: Database username
required: true
parameterType: string
- name: db_password
description: Database user password
required: true
parameterType: base64
- name: db_port
description: Database port
required: true
parameterType: int
"#;

let parameter_file = ParameterFile::from_str(parameter_file_contents.to_string()).unwrap();
let template = Template::new(
template_contents.to_string(),
parameter_file.parameters,
Some(Secrets::new()),
).unwrap();

let processed_template = template.process().unwrap();

assert_eq!(
processed_template.lines().map(|l| l.trim_right()).collect::<Vec<&str>>().join("\n"),
r#"---
apiVersion: v1
kind: Pod
metadata:
name: db_app
spec:
containers:
-
env:
-
name: USERNAME
value: bob
-
name: PASSWORD
value: "Y2hhbmdlbWU="
-
name: DB_PORT
value: "1234"
image: mydb
name: mydb"#
);
}
}
43 changes: 38 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::process::exit;

use clap::{App, AppSettings, Arg, Values};

use ktmpl::{Template, ParameterValue, ParameterValues, Secret, Secrets};
use ktmpl::{Template, ParameterValue, ParameterValues, ParameterFile, Secret, Secrets};

fn main() {
if let Err(error) = real_main() {
Expand Down Expand Up @@ -64,12 +64,31 @@ fn real_main() -> Result<(), String> {
.number_of_values(2)
.value_names(&["NAME", "NAMESPACE"])
)
.arg(
Arg::with_name("parameter-file")
.help("Supplies a Yaml file defining any named parameters")
.next_line_help(true)
.long("parameter-file")
.short("f")
.multiple(true)
.takes_value(true)
.number_of_values(1)
.value_names(&["FILENAME"])
)
.get_matches();

let mut values = match matches.values_of("parameter") {
Some(parameters) => parameter_values(parameters, false),
None => HashMap::new(),
};
let mut values = HashMap::new();

// Parse Parameter files first, passing command line parameters
// should override any values supplied via a file
if let Some(files) = matches.values_of("parameter-file") {
let params_from_file = parameter_files(files);
values.extend(params_from_file);
}

if let Some(parameters) = matches.values_of("parameter") {
values.extend(parameter_values(parameters, false));
}

if let Some(parameters) = matches.values_of("base64-parameter") {
let encoded_values = parameter_values(parameters, true);
Expand Down Expand Up @@ -104,6 +123,20 @@ fn real_main() -> Result<(), String> {
}
}

fn parameter_files(mut param_files: Values) -> ParameterValues {
let mut parameter_values = ParameterValues::new();

loop {
if let Some(f) = param_files.next() {
let param_file = ParameterFile::from_file(&f).unwrap();
parameter_values.extend(param_file.parameters);
} else {
break;
}
}
parameter_values
}

fn parameter_values(mut parameters: Values, base64_encoded: bool) -> ParameterValues {
let mut parameter_values = ParameterValues::new();

Expand Down
93 changes: 93 additions & 0 deletions src/parameterfile.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use std::error::Error;
use std::fs::File;
use std::io::Read;

use yaml::{Yaml, YamlLoader};
use parameter::{ParameterValue, ParameterValues};

#[derive(Debug)]
/// ParameterFile struct
pub struct ParameterFile {
/// filename
pub filename: String,
/// document string
pub doc_str: String,
/// parameters allocated from this file
pub parameters: ParameterValues,
}

fn parse_document(doc_str: &String, parameter_values: &mut ParameterValues) {
let docs = YamlLoader::load_from_str(doc_str).unwrap();
for doc in &docs {
let primary_key = "";
let param_values = parse_yaml(doc, primary_key);
parameter_values.extend(param_values);
}
}

fn parse_yaml(doc: &Yaml, primary_key: &str) -> ParameterValues {
let mut param_values = ParameterValues::new();
match doc {
&Yaml::Hash(ref h) => {
for (key,value) in h {
let combined_key = primary_key.to_string() + key.as_str().unwrap();
match value {
&Yaml::String(ref s) => {
let pv = ParameterValue::Plain(s.to_string());
param_values.insert(combined_key,pv);
},
&Yaml::Integer(ref i) => {
let pv = ParameterValue::Plain(i.to_string());
param_values.insert(combined_key,pv);
},
&Yaml::Real(ref r) => {
let pv = ParameterValue::Plain(r.to_string());
param_values.insert(combined_key,pv);
},
_ => {
// Value type not supported
// Array, Alias and None
}
}
}
},
&Yaml::String(ref s) => {
let pv = ParameterValue::Plain(s.to_string());
param_values.insert(primary_key.to_string(),pv);
},
_ => {
// Key type not supported
}
}
param_values
}

impl ParameterFile {
/// Create a new parameterfile object, composed of a filename
/// and the parsed parameters
pub fn from_file(filename: &str) -> Result<Self, String> {
let mut parameter_values = ParameterValues::new();
let mut fh = File::open(filename).map_err(|err| err.description().to_owned()).unwrap();
let mut contents = String::new();
fh.read_to_string(&mut contents).map_err(|err| err.description().to_owned())?;
parse_document(&contents, &mut parameter_values);

Ok(ParameterFile {
filename: String::from(filename),
doc_str: String::from(contents),
parameters: parameter_values,
})
}

/// Create a new parameterfile object from a String representing a yaml document
pub fn from_str(doc_str: String) -> Result<Self, String> {
let mut parameter_values = ParameterValues::new();
parse_document(&doc_str, &mut parameter_values);

Ok(ParameterFile {
filename: String::from(""),
doc_str: String::from(doc_str),
parameters: parameter_values,
})
}
}

0 comments on commit c43cdea

Please sign in to comment.