Skip to content

Commit

Permalink
Fixes #17585: dsc integration
Browse files Browse the repository at this point in the history
  • Loading branch information
gpoblon committed Jun 23, 2020
1 parent a56fe67 commit 89651a6
Show file tree
Hide file tree
Showing 8 changed files with 1,184 additions and 232 deletions.
706 changes: 528 additions & 178 deletions rudder-lang/libs/resourcelib.rl

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions rudder-lang/src/generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
// SPDX-FileCopyrightText: 2019-2020 Normation SAS

mod cfengine;
mod dsc;

pub use self::cfengine::CFEngine;
pub use self::dsc::DSC;
use crate::ast::AST;
use crate::error::*;
use serde::de::{self, Deserialize, Deserializer};
Expand All @@ -26,10 +28,10 @@ pub trait Generator {
) -> Result<()>;
}

pub fn new_generator(format: &Format) -> Result<impl Generator> {
pub fn new_generator(format: &Format) -> Result<Box<dyn Generator>> {
match format {
Format::CFEngine => Ok(CFEngine::new()),
// Format::DSC => Ok(DSC::new()),
Format::CFEngine => Ok(Box::new(CFEngine::new())),
Format::DSC => Ok(Box::new(DSC::new())),
// Format::JSON => Ok(JSON::new()),
_ => Err(Error::User(format!("No Generator for {} format", format))),
}
Expand All @@ -50,7 +52,7 @@ impl fmt::Display for Format {
"{}",
match self {
Format::CFEngine => "cf",
Format::DSC => "dsc",
Format::DSC => "ps1",
Format::RudderLang => "rl",
Format::JSON => "json",
}
Expand All @@ -64,7 +66,7 @@ impl FromStr for Format {
fn from_str(format: &str) -> Result<Self> {
match format {
"cf" | "cfengine" => Ok(Format::CFEngine),
"dsc" => Ok(Format::DSC),
"dsc" | "ps1" => Ok(Format::DSC),
"json" => Ok(Format::JSON),
"rl" => Ok(Format::RudderLang),
// RudderLang is an error, not a compilation format
Expand Down
97 changes: 55 additions & 42 deletions rudder-lang/src/generators/cfengine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ pub struct CFEngine {
}

impl CFEngine {
pub fn new() -> CFEngine {
CFEngine {
pub fn new() -> Self {
Self {
current_cases: Vec::new(),
var_prefixes: HashMap::new(),
prefixes: HashMap::new(),
Expand All @@ -54,20 +54,17 @@ impl CFEngine {

fn parameter_to_cfengine(&mut self, param: &Value) -> Result<String> {
Ok(match param {
Value::String(s) =>
// TODO variable reinterpret (rudlang systemvar to cfengine systemvar)
{
"\"".to_owned()
+ s.format(
|x: &str| {
x.replace("\\", "\\\\") // backslash escape
.replace("\"", "\\\"") // quote escape
.replace("$", "${const.dollar}")
}, // dollar escape
|y: &str| "${".to_owned() + y + "}", // variable inclusion
)
.as_str()
+ "\""
Value::String(s) => {
// TODO variable reinterpret (rudlang systemvar to cfengine systemvar)
let formatted_param = s.format(
|x: &str| {
x.replace("\\", "\\\\") // backslash escape
.replace("\"", "\\\"") // quote escape
.replace("$", "${const.dollar}")
}, // dollar escape
|y: &str| format!("${{{}}}", y), // variable inclusion
);
format!(r#""{}""#, formatted_param)
}
Value::Number(_, _) => unimplemented!(),
Value::Boolean(_, _) => unimplemented!(),
Expand Down Expand Up @@ -369,7 +366,7 @@ impl CFEngine {
let mut metadatas = String::new();
let mut push_metadata = |entry: &str| {
if let Some(val) = map.remove(entry) {
metadatas.push_str(&format!("# @{} {}\n", entry, val));
metadatas.push_str(&format!("# @{} {:#?}\n", entry, val));
}
};
push_metadata("name");
Expand Down Expand Up @@ -406,8 +403,9 @@ impl Generator for CFEngine {
None => continue,
};
self.reset_context();
let mut content = "# generated by rudder-lang\n".to_owned();
let fileinfo = match files.get(&file_to_create) {

// get header
let header = match files.get(&file_to_create) {
Some(s) => s.to_string(),
None => {
if technique_metadata {
Expand All @@ -417,46 +415,61 @@ impl Generator for CFEngine {
}
}
};
content.push_str(&fileinfo);
let mut params = res

// get parameters
let mut parameters = res
.parameters
.iter()
.chain(state.parameters.iter())
.map(|p| p.name.fragment())
.collect::<Vec<&str>>()
.join(",");
if !params.is_empty() {
params = format!("({})", params);
if !parameters.is_empty() {
parameters = format!("({})", parameters);
}
content.push_str(&format!(
"bundle agent {}_{}{}\n",
rn.fragment(),
sn.fragment(),
params
));
content.push_str(
"{\n vars:\n \"resources_dir\" string => \"${this.promise_dirname}/resources\";\n"

// get methods
let methods: String = state
.statements
.iter()
.enumerate()
.map(|(i, st)| {
self.format_statement(gc, st, i, "any".to_string(), generic_methods)
})
.collect::<Result<Vec<String>>>()?
.join("\n");

// merge header + parameters + methods with technique file body
let content = format!(
r#"# generated by rudder-lang
{header}
bundle agent {resource_name}_{state_name}{parameters}
{{
vars:
"resources_dir" string => "${{this.promise_dirname}}/resources";
methods:
{methods}
}}"#,
header = header,
resource_name = rn.fragment(),
state_name = sn.fragment(),
parameters = parameters,
methods = methods
);
content.push_str(" methods:\n");
for (i, st) in state.statements.iter().enumerate() {
content.push_str(&self.format_statement(
gc,
st,
i,
"any".to_string(),
generic_methods,
)?);
}
content.push_str("}\n");
files.insert(file_to_create, content);
}
}
// create file if needed
if files.is_empty() {
match dest_file {
Some(filename) => File::create(filename).expect("Could not create output file"),
None => return Err(Error::User("No file to create".to_owned())),
};
}

// write to file
for (name, content) in files.iter() {
let mut file = File::create(name).expect("Could not create output file");
file.write_all(content.as_bytes())
Expand Down
Loading

0 comments on commit 89651a6

Please sign in to comment.