Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
gpoblon committed Jul 9, 2020
1 parent 745f8a4 commit dd853a7
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 77 deletions.
35 changes: 35 additions & 0 deletions rudder-lang/src/parser/baseparsers.rs
Expand Up @@ -205,3 +205,38 @@ pub fn pvariable_identifier(i: PInput) -> PResult<Token> {
|x: PInput| x.into(),
)(i)
}

/// A variable identifier is a list of dot separated identifiers
pub fn pvariable_identifier(i: PInput) -> PResult<Token> {
map(
take_while1(|c: char| c.is_alphanumeric() || (c == '_') || (c == '.')),
|x: PInput| x.into(),
)(i)
}
fn ptemplate_identifier](i: PInput) -> PResult<Token> {
alt((
many1(alt((
// variable ${}
map(
delimited(tag("${"), parse_cfvariable, tag("}")),
CFStringElt::Variable,
),
// variable $()
map(
delimited(tag("$("), parse_cfvariable, tag(")")),
CFStringElt::Variable,
),
// constant
map(take_until("$"), |s: &str| CFStringElt::Static(s.into())),
// end of string
map(
preceded(
peek(anychar), // do no take rest if we are already at the end
rest,
),
|s: &str| CFStringElt::Static(s.into()),
),
))),
// empty string
)))(i)
}
76 changes: 51 additions & 25 deletions rudder-lang/src/translate.rs
Expand Up @@ -49,9 +49,21 @@ struct MethodCall {

#[derive(Serialize, Deserialize, Default)]
struct Parameter {
name: String,
name: Option<String>,
value: String,
}
impl Parameter {
pub fn new(name: Option<&str>, value: &str) -> Self {
let owned_name = match name {
Some(n) => Some(n.to_owned()),
None => None
};
Self {
name: owned_name,
value: value.to_owned()
}
}
}

pub fn translate_file(context: &IOContext) -> Result<()> {
let input_path = context.source.to_string_lossy();
Expand Down Expand Up @@ -91,7 +103,10 @@ pub fn translate_file(context: &IOContext) -> Result<()> {
let mut technique = serde_json::from_str::<Technique>(&json_data)
.map_err(|e| err!(Token::new(&input_path, ""), "{}", e))?;

technique.method_calls.iter_mut().for_each(|method| method.args.push(method.parameters.iter().map(|p| p.value.to_owned()).collect()));
technique.method_calls.iter_mut().for_each(|method| {
method.parameters.extend(method.args.iter().map(|v| Parameter::new(None, v)).collect::<Vec<Parameter>>())
});


info!(
"|- {} (translation phase)",
Expand Down Expand Up @@ -168,6 +183,28 @@ resource {bundle_name}({parameter_list})
_ => panic!(format!("The standard library contains several matches for the following method: {}", method_name))
}
}

fn translate_args<I>(&self, args: I, template_vars: &mut Vec<String>) -> Result<String>
where I: Iterator<Item = &'src Parameter>
{
let mut updated_args = Vec::new();
for arg in args {
// rl v2 behavior should make use of this, for now, just a syntax validator
if parse_cfstring(&arg.value).is_err() {
return Err(Error::User(format!("Invalid variable syntax in '{}'", arg.value)));
}
if arg.value.contains("$") {
updated_args.push(format!("p{}", template_vars.len()));
template_vars.push(format!(" p{}=\"{}\"", template_vars.len(), arg.value));
} else {
updated_args.push(format!("\"{}\"", arg.value));
}
}

let validated_args = map_strings_results(updated_args.iter(), |x| Ok(x.to_owned()), ",")?;

Ok(validated_args)
}

fn translate_call(&self, call: &MethodCall) -> Result<String> {
let (resource, state) = match self.get_method_from_stdlib(&call.method_name) {
Expand All @@ -194,9 +231,13 @@ resource {bundle_name}({parameter_list})
}
Some(v) => v as usize,
};
let it = &mut call.args.iter();
let res_args = map_strings_results(it.take(res_arg_count), |x| self.translate_arg(x), ",")?;
let st_args = map_strings_results(it, |x| self.translate_arg(x), ",")?;

let it = &mut call.parameters.iter();
let mut template_vars = Vec::new();
let res_args = self.translate_args(it.take(res_arg_count), &mut template_vars)?; // automatically takes the first rather than getting the right resource param index
let st_args = self.translate_args(it, &mut template_vars)?;
// empty string purpose: add an ending newline when joined into a string
template_vars.push(String::new());

// call formating
let call_str = format!("{}({}).{}({})", &resource, res_args, &state, st_args);
Expand Down Expand Up @@ -239,13 +280,13 @@ resource {bundle_name}({parameter_list})
}
Some(m) => m.as_integer().unwrap(),
};
let class_parameter_value = &call.args[class_parameter_id as usize];
let canonic_parameter = canonify(class_parameter_value);
let class_parameter = &call.parameters[class_parameter_id as usize];
let canonic_parameter = canonify(&class_parameter.value);
let outcome = format!(" as {}_{}", class_prefix, canonic_parameter);
// TODO remove outcome if there is no usage
Ok(format!(
" @component = \"{}\"\n{}{}",
&call.component, out_state, outcome
"{} @component = \"{}\"\n{}{}",
template_vars.join("\n"), &call.component, out_state, outcome
))
}

Expand Down Expand Up @@ -287,15 +328,6 @@ resource {bundle_name}({parameter_list})
Ok((parameters_meta, parameter_list))
}

fn translate_arg(&self, arg: &str) -> Result<String> {
let var = match parse_cfstring(arg) {
Err(_) => return Err(Error::User(format!("Invalid variable syntax in '{}'", arg))),
Ok((_, o)) => o,
};

map_strings_results(var.iter(), |x| Ok(format!("\"{}\"", x.to_string()?)), ",")
}

fn translate_condition(&self, expr: &str) -> Result<String> {
lazy_static! {
static ref CLASS_RE: Regex = Regex::new(r"([\w${}.]+)").unwrap();
Expand Down Expand Up @@ -355,10 +387,9 @@ resource {bundle_name}({parameter_list})
} else if vec!["error", "not_ok", "failed", "denied", "timeout", "not_kept"].iter().any(|x| x == &outcome)
{
return Ok(format!("{} =~ error", method));
} else if vec!["repaired", "ok", "reached"].iter().any(|x| x == &outcome)
} else if vec!["repaired", "ok", "reached", "true", "false"].iter().any(|x| x == &outcome)
{
return Ok(format!("{} =~ {}", method, outcome));
} else if cond == "" {
}
};

Expand Down Expand Up @@ -469,11 +500,6 @@ fn parse_cfstring(i: &str) -> IResult<&str, Vec<CFStringElt>> {
delimited(tag("${"), parse_cfvariable, tag("}")),
CFStringElt::Variable,
),
// variable $()
map(
delimited(tag("$("), parse_cfvariable, tag(")")),
CFStringElt::Variable,
),
// constant
map(take_until("$"), |s: &str| CFStringElt::Static(s.into())),
// end of string
Expand Down
98 changes: 49 additions & 49 deletions rudder-lang/tests/test_files/translate/cis.json
@@ -1,57 +1,57 @@
{
"bundle_name": "CIS_redhat7___Enable_Service",
"description": "test",
"name": "CIS redhat7 - Enable Service",
"version": "1.0",
"parameter": [
"bundle_name": "CIS_redhat7___Enable_Service",
"description": "test",
"name": "CIS redhat7 - Enable Service",
"version": "1.0",
"parameter": [
{
"id": "981a5b9d-b062-4011-8dff-df1810cb2fe6",
"name": "service",
"description": ""
}
],
"category": "CIS_redhat7",
"method_calls": [
{
"parameters": [
{
"name": "condition_prefix",
"value": "skip_item_${report_data.canonified_directive_id}",
"$errors": []
},
{
"id": "981a5b9d-b062-4011-8dff-df1810cb2fe6",
"name": "service",
"description": ""
"name": "variable_name",
"value": "node.properties[skip][${report_data.directive_id}]",
"$errors": []
}
],
"category": "CIS_redhat7",
"method_calls": [
{
"parameters": [
{
"name": "condition_prefix",
"value": "skip_item_${report_data.canonified_directive_id}",
"$errors": []
},
{
"name": "variable_name",
"value": "node.properties[skip][${report_data.directive_id}]",
"$errors": []
}
],
"class_context": "any",
"method_name": "condition_from_variable_existence",
"component": "condition_from_variable_existence"
},
"class_context": "any",
"method_name": "condition_from_variable_existence",
"component": "condition_from_variable_existence"
},
{
"parameters": [
{
"parameters": [
{
"name": "service_name",
"value": "${service}",
"$errors": []
}
],
"class_context": "any.(skip_item_${report_data.canonified_directive_id}_ok)",
"method_name": "service_enabled",
"component": "service_enabled"
},
"name": "service_name",
"value": "${service}",
"$errors": []
}
],
"class_context": "any.(skip_item_${report_data.canonified_directive_id}_false)",
"method_name": "service_enabled",
"component": "service_enabled"
},
{
"parameters": [
{
"parameters": [
{
"name": "service_name",
"value": "${service}",
"$errors": []
}
],
"class_context": "any.(skip_item_${report_data.canonified_directive_id}_not_ok)",
"method_name": "service_started",
"component": "service_started"
"name": "service_name",
"value": "${service}",
"$errors": []
}
]
],
"class_context": "any.(skip_item_${report_data.canonified_directive_id}_false)",
"method_name": "service_started",
"component": "service_started"
}
]
}
10 changes: 7 additions & 3 deletions rudder-lang/tests/test_files/translate/cis.rl
Expand Up @@ -9,10 +9,14 @@

resource CIS_redhat7___Enable_Service(service)
CIS_redhat7___Enable_Service state technique() {
p0 = "skip_item_${report_data.canonified_directive_id}"
p1 = "node.properties[skip][${report_data.directive_id}]"
@component = "condition_from_variable_existence"
condition("skip_item_","${report_data.canonified_directive_id}","node.properties[skip][","${report_data.directive_id}","]").from_variable_existence() as condition_from_variable_existence_skip_item___report_data_canonified_directive_id_node_properties_skip____report_data_directive_id__
condition(p0).from_variable_existence(p1) as condition_from_variable_existence_skip_item___report_data_canonified_directive_id_
p0 = "${service}"
@component = "service_enabled"
if (skip_item_${report_data.canonified_directive_id} =~ ok) => service("service").enabled() as service_enabled___service_
if (skip_item_${report_data.canonified_directive_id} =~ false) => service(p0).enabled() as service_enabled___service_
p0 = "${service}"
@component = "service_started"
if (skip_item_${report_data.canonified_directive_id} =~ error) => service("service").started() as service_started___service_
if (skip_item_${report_data.canonified_directive_id} =~ false) => service(p0).started() as service_started___service_
}
14 changes: 14 additions & 0 deletions rudder-lang/tests/test_files/translate/cis.rl.cf
@@ -0,0 +1,14 @@
# generated by rudder-lang
# @name CIS redhat7 - Enable Service
# @description test
# @version 1.0
# @parameter { "name": "service", "id": "981a5b9d-b062-4011-8dff-df1810cb2fe6", "constraints": "" }

bundle agent CIS_redhat7___Enable_Service_technique(service)
{
vars:
"resources_dir" string => "${this.promise_dirname}/resources";
methods:
"condition_from_variable_existence_${report_data.directive_id}_0" usebundle => _method_reporting_context("condition_from_variable_existence", "skip_item_");
"condition_from_variable_existence_${report_data.directive_id}_0" usebundle => condition_from_variable_existence("skip_item_", "${report_data.canonified_directive_id}");
}
13 changes: 13 additions & 0 deletions rudder-lang/tests/test_files/translate/s_basic.rl
@@ -0,0 +1,13 @@
# This file has been generated with rltranslate
@format=0
@name="Configure NTP"
@description="test"
@version="1.0"
@parameters= [
]

resource Configure_NTP()
Configure_NTP state technique() {
@component = "Package present"
package("ntp").present("","","") as package_present_ntp
}
19 changes: 19 additions & 0 deletions rudder-lang/tests/test_files/translate/s_ntp.rl.cf
@@ -0,0 +1,19 @@
# generated by rudder-lang
# @name NTP Technique
# @description Configure the NTP
# @version 1.1

bundle agent NTP_Technique_technique
{
vars:
"resources_dir" string => "${this.promise_dirname}/resources";
methods:
"Package install_${report_data.directive_id}_0" usebundle => _method_reporting_context("Package install", "ntp");
"Package install_${report_data.directive_id}_0" usebundle => package_install("ntp");
"File ensure lines present_${report_data.directive_id}_1" usebundle => _method_reporting_context("File ensure lines present", "/etc/ntp.conf");
"File ensure lines present_${report_data.directive_id}_1" usebundle => file_ensure_lines_present("/etc/ntp.conf", "server pool.ntp.org");
"Service restart_${report_data.directive_id}_2" usebundle => _method_reporting_context("Service restart", "ntp"),
if => concat("file_ensure_lines_present__etc_ntp_conf1_outcome_repaired");
"Service restart_${report_data.directive_id}_2" usebundle => service_restart("ntp"),
if => concat("file_ensure_lines_present__etc_ntp_conf1_outcome_repaired");
}

0 comments on commit dd853a7

Please sign in to comment.