Example #1
0
def get_technique_expected_reports(technique_metadata):
    """Generates technique expected reports from technique metadata"""
    # Get all generic methods
    generic_methods = ncf.get_all_generic_methods_metadata()

    # Content start with a header
    content = [
        """# This file contains one line per report expected by Rudder from this technique
# Format: technique_name;;class_prefix_${key};;@@RUDDER_ID@@;;component name;;component key"""
    ]

    technique_name = technique_metadata['bundle_name']
    for method_call in technique_metadata["method_calls"]:
        method_name = method_call['method_name']
        generic_method = generic_methods[method_name]

        component = generic_method['name']
        key_value = method_call["args"][generic_method["class_parameter_id"] -
                                        1]
        class_prefix = generic_method["class_prefix"] + "_" + key_value

        line = technique_name + ";;" + class_prefix + ";;@@RUDDER_ID@@;;" + component + ";;" + key_value

        content.append(line)

    # Join all lines + last line
    result = "\n".join(content) + "\n"
    return result
Example #2
0
def get_technique_metadata_xml(technique_metadata):
  """Get metadata xml for a technique as string"""

  # Get all generic methods
  generic_methods = ncf.get_all_generic_methods_metadata()

  content = []
  content.append('<TECHNIQUE name="'+technique_metadata['name']+'">')
  content.append('  <DESCRIPTION>'+technique_metadata['description']+'</DESCRIPTION>')
  content.append('  <BUNDLES>')
  content.append('    <NAME>'+ technique_metadata['bundle_name'] + '</NAME>')
  content.append('  </BUNDLES>')
  content.append('  <SECTIONS>')

  method_calls = technique_metadata["method_calls"]  

  # Get all method call, with no duplicate values
  methods_name = set()
  for method_call in method_calls:
    method_name = methods_name.add(method_call['method_name'])

  # For each method used, create a section containing all calls to that method
  section_list = []
  for method_name in methods_name:

    try:
      generic_method = generic_methods[method_name]
    except Exception, e:
      print "Error: The method '" + method_name + "' does not exist. Aborting Technique creation..."

    # Filter all method calls to get only those about that method
    filter_method_calls = [x for x in method_calls if x["method_name"] == method_name]
    # Generare xml for that section
    section = generate_section_xml(filter_method_calls, generic_method)
    section_list.extend(section)
Example #3
0
def get_technique_expected_reports(technique_metadata):
    """Generates technique expected reports from technique metadata"""
    # Get all generic methods
    generic_methods = ncf.get_all_generic_methods_metadata(
        alt_path='/var/rudder/configuration-repository/ncf'
    )["data"]['generic_methods']

    # Content start with a header
    content = [
        """# This file contains one line per report expected by Rudder from this technique
# Format: technique_name;;class_prefix_${key};;@@RUDDER_ID@@;;component name;;component key"""
    ]

    technique_name = technique_metadata['bundle_name']
    for method_call in technique_metadata["method_calls"]:
        # Expected reports for Rudder should not include any "meta" bundle calls (any beginning with _)
        if method_call['method_name'].startswith("_"):
            continue

        method_name = method_call['method_name']
        generic_method = generic_methods[method_name]

        component = generic_method['name']
        key_value = method_call["args"][generic_method["class_parameter_id"] -
                                        1]
        class_prefix = (generic_method["class_prefix"] + "_" +
                        key_value).replace("\\'", "\'").replace('\\"', '\"')

        line = technique_name + ";;" + class_prefix + ";;@@RUDDER_ID@@;;" + component + ";;" + key_value

        content.append(line)

    # Join all lines + last line
    result = "\n".join(content) + "\n"
    return result
Example #4
0
def get_technique_expected_reports(technique_metadata):
  """Generates technique expected reports from technique metadata"""
  # Get all generic methods
  generic_methods = ncf.get_all_generic_methods_metadata(alt_path='/var/rudder/configuration-repository/ncf')["data"]['generic_methods']

  # Content start with a header
  content = ["""# This file contains one line per report expected by Rudder from this technique
# Format: technique_name;;class_prefix_${key};;@@RUDDER_ID@@;;component name;;component key"""]
  
  technique_name = technique_metadata['bundle_name']
  for method_call in technique_metadata["method_calls"]:
    # Expected reports for Rudder should not include any "meta" bundle calls (any beginning with _)
    if method_call['method_name'].startswith("_"):
      continue

    method_name = method_call['method_name']
    generic_method = generic_methods[method_name]

    component = generic_method['name']
    key_value = method_call["args"][generic_method["class_parameter_id"]-1]
    class_prefix = (generic_method["class_prefix"]+"_"+key_value).replace("\\'", "\'").replace('\\"', '\"')

    line = technique_name+";;"+class_prefix+";;@@RUDDER_ID@@;;"+component+";;"+key_value
    
    content.append(line)

  # Join all lines + last line
  result = "\n".join(content)+"\n"
  return result
Example #5
0
    def test_get_all_generic_methods_metadata_with_arg(self):
        """get_all_generic_methods_metadata should return a list of all generic_methods with all defined metadata tags"""
        metadata = ncf.get_all_generic_methods_metadata(
        )["data"]["generic_methods"]

        number_generic_methods = len(ncf.get_all_generic_methods_filenames())
        self.assertEqual(number_generic_methods, len(metadata))
Example #6
0
def get_technique_expected_reports(technique_metadata):
    """Generates technique expected reports from technique metadata"""
    # Get all generic methods
    generic_methods = ncf.get_all_generic_methods_metadata()

    # Content start with a header
    content = [
        """# This file contains one line per report expected by Rudder from this technique
# Format: technique_name;;class_prefix_${key};;@@RUDDER_ID@@;;component name;;component key"""
    ]

    technique_name = technique_metadata["bundle_name"]
    for method_call in technique_metadata["method_calls"]:
        # Expected reports for Rudder should not include any "meta" bundle calls (any beginning with _)
        if method_call["method_name"].startswith("_"):
            continue

        method_name = method_call["method_name"]
        generic_method = generic_methods[method_name]

        component = generic_method["name"]
        key_value = method_call["args"][generic_method["class_parameter_id"] - 1]
        class_prefix = generic_method["class_prefix"] + "_" + key_value

        line = technique_name + ";;" + class_prefix + ";;@@RUDDER_ID@@;;" + component + ";;" + key_value

        content.append(line)

    # Join all lines + last line
    result = "\n".join(content) + "\n"
    return result
Example #7
0
  def setUp(self):
    self.test_technique_file = os.path.realpath('test_technique.cf')
    self.test_generic_method_file = 'test_generic_method.cf'
    with open(self.test_technique_file) as fd:
      self.technique_content = fd.read()
    with open(self.test_generic_method_file) as fd:
      self.generic_method_content = fd.read()
    self.all_methods = ncf.get_all_generic_methods_metadata()["data"]["generic_methods"]

    self.technique_metadata = ncf.parse_technique_metadata(self.technique_content)['result']
    method_calls = ncf.parse_technique_methods(self.test_technique_file)
    self.technique_metadata['method_calls'] = method_calls

    self.technique_metadata_test = { 'name': 'ncf technique method argument escape test', 'description': "This is a bundle to test ncf's Python lib", 'version': '0.1', 'bundle_name': 'content_escaping_test', 'bundle_args': [],
        'method_calls': [
            { 'method_name': 'package_install_version', 'args': ['apache2', '2.2.11'], 'class_context': 'any' },
            { 'method_name': 'file_replace_lines', 'args': ['/etc/httpd/conf/httpd.conf', 'ErrorLog \"/var/log/httpd/error_log\"', 'ErrorLog "/projet/logs/httpd/error_log"'],  'class_context': 'redhat' },
          ]
        }
    self.technique_metadata_test_content = os.path.realpath('technique_metadata_test_content.cf')
    all_tags = ncf.tags["generic_method"]+ncf.tags["common"]
    self.methods_expected_tags = [ tag for tag in all_tags if not tag in ncf.optionnal_tags ]

    with open(self.technique_metadata_test_content) as fd:
      self.technique_test_expected_content = fd.read()
Example #8
0
  def test_get_all_generic_methods_metadata_with_arg(self):
    """get_all_generic_methods_metadata should return a list of all generic_methods with all defined metadata tags"""
    alternative_path = os.path.dirname(os.path.realpath(__file__)) + "/test_methods"
    metadata = ncf.get_all_generic_methods_metadata(alternative_path)["data"]

    number_generic_methods = len(ncf.get_all_generic_methods_filenames(alternative_path))
    self.assertEquals(number_generic_methods, len(metadata))
Example #9
0
    def setUp(self):
        self.test_technique_file = os.path.realpath('test_technique.cf')
        self.test_generic_method_file = 'test_generic_method.cf'
        with open(self.test_technique_file) as fd:
            self.technique_content = fd.read()
        with open(self.test_generic_method_file) as fd:
            self.generic_method_content = fd.read()
        self.all_methods = ncf.get_all_generic_methods_metadata(
        )["data"]["generic_methods"]

        self.technique_metadata = ncf.parse_technique_metadata(
            self.technique_content)['result']
        method_calls = ncf.parse_technique_methods(self.test_technique_file,
                                                   self.all_methods)
        self.technique_metadata['method_calls'] = method_calls

        self.technique_metadata_test = {
            'name':
            'ncf technique method argument escape test',
            'description':
            "This is a bundle to test ncf's Python lib",
            'version':
            '0.1',
            'bundle_name':
            'content_escaping_test',
            'bundle_args': [],
            'parameter': [],
            'method_calls': [
                {
                    'method_name': 'package_install_version',
                    "component": "Install a package with correct version",
                    'args': ['apache2', '2.2.11'],
                    'class_context': 'any'
                },
                {
                    'method_name':
                    'file_replace_lines',
                    "component":
                    "Edit conf file",
                    'args': [
                        '/etc/httpd/conf/httpd.conf',
                        'ErrorLog \"/var/log/httpd/error_log\"',
                        'ErrorLog "/projet/logs/httpd/error_log"'
                    ],
                    'class_context':
                    'redhat'
                },
            ]
        }
        self.technique_metadata_test_content = os.path.realpath(
            'technique_metadata_test_content.cf')
        all_tags = ncf.tags["generic_method"]
        self.methods_expected_tags = [
            tag for tag in all_tags
            if not tag in ncf.optionnal_tags["generic_method"]
        ]

        with open(self.technique_metadata_test_content) as fd:
            self.technique_test_expected_content = fd.read().split("\n")
Example #10
0
def generate_rudder_reporting(technique):
  """Generate complementary reporting needed for Rudder in rudder_reporting.st file"""
  # Get all generic methods
  generic_methods = ncf.get_all_generic_methods_metadata(alt_path='/var/rudder/configuration-repository/ncf')['data']['generic_methods']

  content = []
  content.append('bundle agent '+ technique['bundle_name']+'_rudder_reporting')
  content.append('{')
  content.append('  vars:')
  content.append('    "promisers"          slist => { @{this.callers_promisers}, cf_null }, policy => "ifdefined";')
  content.append('    "class_prefix"      string => canonify(join("_", "promisers"));')
  content.append('    "args"               slist => { };')
  content.append('')
  content.append('  methods:')

  # Handle method calls
  technique_name = technique['bundle_name']
  # Filter calls so we only have those who are not using a any class_context
  filter_calls = [ method_call for method_call in technique["method_calls"] if method_call['class_context'] != "any" ]

  for method_call in filter_calls:
     
    method_name = method_call['method_name']
    generic_method = generic_methods[method_name]

    key_value = method_call["args"][generic_method["class_parameter_id"]-1].replace("\\'", "\'")
    regex = re.compile("[^\$\{\}a-zA-Z0-9_](?![^{}]+})|\$(?!{)")
    # to match cfengine behaviour we need to treat utf8 as if it was ascii (see #7195)
    # string should be unicode string (ie u'') which is the case if they are read from files opened with encoding="utf-8"
    key_value = key_value.encode("utf-8").decode("iso-8859-1") 
    key_value_canonified = regex.sub("_", key_value)

    class_prefix = generic_method["class_prefix"]+"_"+key_value_canonified
    logger_rudder_call = '"dummy_report" usebundle => log_rudder("' + generic_method['name'] + ' ' + key_value + ' if ' + method_call['class_context'] + '", "' + class_prefix +'", "${class_prefix}", @{args})'
    logger_rudder_call = logger_rudder_call.replace("&", "\\&")

    # Always add an empty line for readability
    content.append('')

    if not "$" in method_call['class_context']:
      content.append('    !('+method_call['class_context']+')::')
      content.append('      "dummy_report" usebundle => _classes_noop("'+class_prefix+'");')
      content.append('      ' + logger_rudder_call + ';')

    else:
      class_context = ncf.canonify_class_context(method_call['class_context'])

      content.append('      "dummy_report" usebundle => _classes_noop("'+class_prefix+'"),')
      content.append('                    ifvarclass => concat("!('+class_context+')");')
      content.append('      ' + logger_rudder_call + ',')
      content.append('                    ifvarclass => concat("!('+class_context+')");')

  content.append('}')

  # Join all lines with \n to get a pretty CFEngine file
  result =  '\n'.join(content)+"\n"

  return result
Example #11
0
def get_technique_metadata_xml(technique_metadata, include_rudder_reporting = False):
  """Get metadata xml for a technique as string"""

  # Get all generic methods
  generic_methods = ncf.get_all_generic_methods_metadata(alt_path='/var/rudder/configuration-repository/ncf')['data']

  content = []
  content.append('<TECHNIQUE name="'+technique_metadata['name']+'">')
  content.append('  <DESCRIPTION>'+technique_metadata['description']+'</DESCRIPTION>')
  content.append('  <BUNDLES>')
  content.append('    <NAME>'+ technique_metadata['bundle_name'] + '</NAME>')
  if include_rudder_reporting:
    content.append('    <NAME>'+ technique_metadata['bundle_name'] + '_rudder_reporting</NAME>')
  content.append('  </BUNDLES>')

  if include_rudder_reporting:
    content.append('  <TMLS>')
    content.append('    <TML name="rudder_reporting"/>')
    content.append('  </TMLS>')

  content.append('  <SECTIONS>')

  method_calls = technique_metadata["method_calls"]  

  # Get all method call, with no duplicate values
  methods_name = set()
  for method_call in method_calls:
    # Expected reports for Rudder should not include any "meta" bundle calls (any beginning with _)
    if method_call['method_name'].startswith("_"):
      continue

    method_name = methods_name.add(method_call['method_name'])

  # For each method used, create a section containing all calls to that method
  section_list = []
  for method_name in methods_name:

    try:
      generic_method = generic_methods[method_name]
    except Exception as e:
      sys.stderr.write("Error: The method '" + method_name + "' does not exist. Aborting Technique creation..." + "\n")
      sys.stderr.write(traceback.format_exc())
      exit(1)

    # Filter all method calls to get only those about that method
    filter_method_calls = [x for x in method_calls if x["method_name"] == method_name]
    # Generare xml for that section
    section = generate_section_xml(filter_method_calls, generic_method)
    section_list.extend(section)

  content.extend(section_list)
  content.append('  </SECTIONS>')
  content.append('</TECHNIQUE>')

  # Join all lines with \n to get a pretty xml
  result =  '\n'.join(content)+"\n"

  return result
Example #12
0
    def test_get_all_generic_methods_metadata_with_arg(self):
        """get_all_generic_methods_metadata should return a list of all generic_methods with all defined metadata tags"""
        alternative_path = os.path.dirname(
            os.path.realpath(__file__)) + "/test_methods"
        metadata = ncf.get_all_generic_methods_metadata(
            alternative_path)["data"]

        number_generic_methods = len(
            ncf.get_all_generic_methods_filenames(alternative_path))
        self.assertEqual(number_generic_methods, len(metadata))
Example #13
0
File: views.py Project: fanf/ncf
def get_generic_methods():
  """Get all generic methods from ncf folder passed as parameter, or default ncf folder if not defined"""
  # We need to get path from url params, if not present put "" as default value
  if "path" in request.args:
    path = request.args['path']
  else:
    path = ""

  generic_methods = ncf.get_all_generic_methods_metadata(alt_path = path)
  resp = jsonify( generic_methods )
  return resp
Example #14
0
File: views.py Project: DINKIN/ncf
def get_generic_methods():
  """Get all generic methods from ncf folder passed as parameter, or default ncf folder if not defined"""
  try:
    # We need to get path from url params, if not present put "" as default value
    path = get_path_from_args(request)
  
    generic_methods = ncf.get_all_generic_methods_metadata(alt_path = path)
    resp = jsonify( generic_methods )
    return resp
  except Exception as e:
    return format_error(e, "generic methods fetching", 500)
Example #15
0
def get_generic_methods():
    """Get all generic methods from ncf folder passed as parameter, or default ncf folder if not defined"""
    try:
        # We need to get path from url params, if not present put "" as default value
        path = get_path_from_args(request)

        generic_methods = ncf.get_all_generic_methods_metadata(alt_path=path)
        resp = jsonify(generic_methods)
        return resp
    except Exception as e:
        return format_error(e, "generic methods fetching", 500)
Example #16
0
def write_technique_for_rudder(root_path, technique):
  """ From a technique, generate all files needed for Rudder in specified path"""

  path = get_path_for_technique(root_path,technique)
  if not os.path.exists(path):
    os.makedirs(path)
  # We don't need to create rudder_reporting.st if all class context are any
  generic_methods = ncf.get_all_generic_methods_metadata(alt_path='/var/rudder/configuration-repository/ncf')['data']['generic_methods']
  include_rudder_reporting = not all(method_call['class_context'] == 'any' and 
                                     "cfengine-community" in generic_methods[method_call['method_name']]["agent_support"] for method_call in technique["method_calls"])
  if include_rudder_reporting:
    write_rudder_reporting_file(path,technique)
Example #17
0
def write_technique_for_rudder(root_path, technique):
  """ From a technique, generate all files needed for Rudder in specified path"""

  path = get_path_for_technique(root_path,technique)
  if not os.path.exists(path):
    os.makedirs(path)
  # We don't need to create rudder_reporting.st if all class context are any
  generic_methods = ncf.get_all_generic_methods_metadata(alt_path='/var/rudder/configuration-repository/ncf')['data']['generic_methods']
  include_rudder_reporting = not all(method_call['class_context'] == 'any' and 
                                     "cfengine-community" in generic_methods[method_call['method_name']]["agent_support"] for method_call in technique["method_calls"])
  write_expected_reports_file(path,technique)
  if include_rudder_reporting:
    write_rudder_reporting_file(path,technique)
Example #18
0
def generate_rudder_reporting(technique):
  """Generate complementary reporting needed for Rudder in rudder_reporting.st file"""
  # Get all generic methods
  generic_methods = ncf.get_all_generic_methods_metadata(alt_path='/var/rudder/configuration-repository/ncf')

  content = []
  content.append('bundle agent '+ technique['bundle_name']+'_rudder_reporting')
  content.append('{')
  content.append('  methods:')

  # Handle method calls
  technique_name = technique['bundle_name']
  # Filter calls so we only have those who are not using a any class_context
  filter_calls = [ method_call for method_call in technique["method_calls"] if method_call['class_context'] != "any" ]

  for method_call in filter_calls:

    method_name = method_call['method_name']
    generic_method = generic_methods[method_name]

    key_value = method_call["args"][generic_method["class_parameter_id"]-1]
    key_value_canonified = re.sub("[^\$\{\}\w](?![^{}]+})|\$(?!{)", "_", key_value)


    class_prefix = generic_method["class_prefix"]+"_"+key_value_canonified

    # Always add an empty line for readability
    content.append('')

    if not "$" in method_call['class_context']:
      content.append('    !('+method_call['class_context']+')::')
      content.append('      "dummy_report" usebundle => _classes_noop("'+class_prefix+'");')
      content.append('      "dummy_report" usebundle => logger_rudder("Not applicable", "'+class_prefix+'");')

    else:
      content.append('      "dummy_report" usebundle => _classes_noop("'+class_prefix+'"),')
      content.append('                    ifvarclass => "!('+method_call['class_context']+')";')
      content.append('      "dummy_report" usebundle => logger_rudder("Not applicable", "'+class_prefix+'"),')
      content.append('                    ifvarclass => "!('+method_call['class_context']+')";')




  content.append('}')

  # Join all lines with \n to get a pretty CFEngine file
  result =  '\n'.join(content)+"\n"

  return result
Example #19
0
def get_technique_metadata_xml(technique_metadata, include_rudder_reporting=False):
    """Get metadata xml for a technique as string"""

    # Get all generic methods
    generic_methods = ncf.get_all_generic_methods_metadata(alt_path="/var/rudder/configuration-repository/ncf")

    content = []
    content.append('<TECHNIQUE name="' + technique_metadata["name"] + '">')
    content.append("  <DESCRIPTION>" + technique_metadata["description"] + "</DESCRIPTION>")
    content.append("  <BUNDLES>")
    content.append("    <NAME>" + technique_metadata["bundle_name"] + "</NAME>")
    if include_rudder_reporting:
        content.append("    <NAME>" + technique_metadata["bundle_name"] + "_rudder_reporting</NAME>")
    content.append("  </BUNDLES>")

    if include_rudder_reporting:
        content.append("  <TMLS>")
        content.append('    <TML name="rudder_reporting"/>')
        content.append("  </TMLS>")

    content.append("  <SECTIONS>")

    method_calls = technique_metadata["method_calls"]

    # Get all method call, with no duplicate values
    methods_name = set()
    for method_call in method_calls:
        # Expected reports for Rudder should not include any "meta" bundle calls (any beginning with _)
        if method_call["method_name"].startswith("_"):
            continue

        method_name = methods_name.add(method_call["method_name"])

    # For each method used, create a section containing all calls to that method
    section_list = []
    for method_name in methods_name:

        try:
            generic_method = generic_methods[method_name]
        except Exception, e:
            print "Error: The method '" + method_name + "' does not exist. Aborting Technique creation..."

        # Filter all method calls to get only those about that method
        filter_method_calls = [x for x in method_calls if x["method_name"] == method_name]
        # Generare xml for that section
        section = generate_section_xml(filter_method_calls, generic_method)
        section_list.extend(section)
Example #20
0
def convert_all_to_dsc(root_path):
    techniques = ncf.get_all_techniques_metadata(
        alt_path=rudder_ncf_path)['data']['techniques']
    methods = ncf.get_all_generic_methods_metadata(
        alt_path=rudder_ncf_path)['data']['generic_methods']
    check_dsc_techniques_path()
    ret = 0
    for technique, metadata in techniques.items():
        try:
            convert_technique(metadata, methods)
        except Exception as e:
            sys.stderr.write(
                "Error: Unable to create Rudder Technique files related to ncf Technique "
                + technique + ", skipping... (" + str(e) + ")\n")
            sys.stderr.write(traceback.format_exc())
            ret = 1
            continue
    exit(ret)
Example #21
0
  def setUp(self):
    self.maxDiff = None
    
    self.test_technique_file = os.path.realpath('test_technique.cf')
    with open(self.test_technique_file) as fd:
      self.technique_content = fd.read()
    self.all_methods = ncf.get_all_generic_methods_metadata()["data"]["generic_methods"]  
    self.technique_metadata = ncf.parse_technique_metadata(self.technique_content)['result']
    method_calls = ncf.parse_technique_methods(self.test_technique_file, self.all_methods)
    self.technique_metadata['method_calls'] = method_calls

    self.test_reporting = os.path.realpath('test_technique_reporting.cf')
    with open(self.test_reporting) as fd:
      self.reporting_content = fd.read()
    self.reporting_metadata = ncf.parse_technique_metadata(self.reporting_content)['result']
    reporting_method_calls = ncf.parse_technique_methods(self.test_reporting, self.all_methods)
    self.reporting_metadata['method_calls'] = reporting_method_calls

    self.test_reporting_with_var = os.path.realpath('test_technique_with_variable.cf')
    with open(self.test_reporting_with_var) as fd:
      self.reporting_with_var_content = fd.read()
    self.reporting_with_var_metadata = ncf.parse_technique_metadata(self.reporting_with_var_content)['result']
    reporting_with_var_method_calls = ncf.parse_technique_methods(self.test_reporting_with_var, self.all_methods)
    self.reporting_with_var_metadata['method_calls'] = reporting_with_var_method_calls


    self.test_any_technique = os.path.realpath('test_technique_any.cf')
    with open(self.test_any_technique) as fd:
      self.any_technique_content = fd.read()
    self.any_technique_metadata = ncf.parse_technique_metadata(self.any_technique_content)['result']
    any_technique_method_calls = ncf.parse_technique_methods(self.test_any_technique, self.all_methods)
    self.any_technique_metadata['method_calls'] = any_technique_method_calls

    self.rudder_reporting_file = os.path.realpath('test_technique_rudder_reporting.cf')
    with open(self.rudder_reporting_file) as fd:
      self.rudder_reporting_content = fd.read()

    # Testing Techniques with quote
    self.test_technique_with_quote_file = os.path.realpath('test_technique_with_quote.cf')
    with open(self.test_technique_with_quote_file) as fd:
      self.technique_with_quote_content = fd.read()
    self.technique_with_quote_metadata = ncf.parse_technique_metadata(self.technique_with_quote_content)['result']
    method_with_quote_calls = ncf.parse_technique_methods(self.test_technique_with_quote_file, self.all_methods)
    self.technique_with_quote_metadata['method_calls'] = method_with_quote_calls
Example #22
0
    def setUp(self):
        self.technique_file = os.path.realpath(
            'technique_metadata_test_content.cf')
        with open(self.technique_file) as fd:
            self.technique_content = fd.read()

        self.all_methods = ncf.get_all_generic_methods_metadata(
        )["data"]["generic_methods"]

        # For test, for now add dsc_support to all method
        for method in self.all_methods:
            self.all_methods[method]["agent_support"] = ["dsc"]

        self.technique_metadata = ncf.parse_technique_metadata(
            self.technique_content)['result']
        method_calls = ncf.parse_technique_methods(self.technique_file)
        self.technique_metadata['method_calls'] = method_calls

        self.dsc_technique_file = os.path.realpath('test_technique.ps1')
        with open(self.dsc_technique_file) as fd:
            self.dsc_content = fd.read()
Example #23
0
def get_technique_metadata_xml(technique_metadata):
    """Get metadata xml for a technique as string"""

    # Get all generic methods
    generic_methods = ncf.get_all_generic_methods_metadata()

    content = []
    content.append('<TECHNIQUE name="' + technique_metadata['name'] + '">')
    content.append('  <DESCRIPTION>' + technique_metadata['description'] +
                   '</DESCRIPTION>')
    content.append('  <BUNDLES>')
    content.append('    <NAME>' + technique_metadata['bundle_name'] +
                   '</NAME>')
    content.append('  </BUNDLES>')
    content.append('  <SECTIONS>')

    method_calls = technique_metadata["method_calls"]

    # Get all method call, with no duplicate values
    methods_name = set()
    for method_call in method_calls:
        method_name = methods_name.add(method_call['method_name'])

    # For each method used, create a section containing all calls to that method
    section_list = []
    for method_name in methods_name:

        try:
            generic_method = generic_methods[method_name]
        except Exception, e:
            print "Error: The method '" + method_name + "' does not exist. Aborting Technique creation..."

        # Filter all method calls to get only those about that method
        filter_method_calls = [
            x for x in method_calls if x["method_name"] == method_name
        ]
        # Generare xml for that section
        section = generate_section_xml(filter_method_calls, generic_method)
        section_list.extend(section)
Example #24
0
def convert_one_to_dsc(destination_path, bundle_name):
    techniques = ncf.get_all_techniques_metadata(
        alt_path=rudder_ncf_path)['data']['techniques']
    methods = ncf.get_all_generic_methods_metadata(
        alt_path=rudder_ncf_path)['data']['generic_methods']
    check_dsc_techniques_path()
    if bundle_name in techniques.keys():
        try:
            metadata = techniques[bundle_name]
            convert_technique(metadata, methods)
        except Exception as e:
            sys.stderr.write(
                "Error: Unable to create Rudder Technique files related to ncf Technique "
                + bundle_name + " (" + str(e) + ")\n")
            sys.stderr.write(traceback.format_exc())
            exit(1)
    else:
        sys.stderr.write(
            "Error: Unable to create Rudder Technique files related to ncf Technique "
            + bundle_name + ", cannot find ncf Technique " + bundle_name +
            "\n")
        sys.stderr.write(traceback.format_exc())
        exit(1)
Example #25
0
def generate_rudder_reporting(technique):
    """Generate complementary reporting needed for Rudder in rudder_reporting.st file"""
    # Get all generic methods
    generic_methods = ncf.get_all_generic_methods_metadata()

    content = []
    content.append("bundle agent " + technique["bundle_name"] + "_rudder_reporting")
    content.append("{")
    content.append("  methods:")

    # Handle method calls
    technique_name = technique["bundle_name"]
    # Filter calls so we only have those who are not using a any class_context
    filter_calls = [method_call for method_call in technique["method_calls"] if method_call["class_context"] != "any"]

    for method_call in filter_calls:

        content.append("    !(" + method_call["class_context"] + ")::")

        method_name = method_call["method_name"]
        generic_method = generic_methods[method_name]

        key_value = method_call["args"][generic_method["class_parameter_id"] - 1]
        key_value_canonified = re.sub("[^a-zA-Z0-9_]", "_", key_value)

        class_prefix = generic_method["class_prefix"] + "_" + key_value_canonified

        content.append('      "dummy_report" usebundle => _classes_noop("' + class_prefix + '");')
        content.append('      "dummy_report" usebundle => logger_rudder("Not applicable", "' + class_prefix + '");')

    content.append("}")

    # Join all lines with \n to get a pretty CFEngine file
    result = "\n".join(content) + "\n"

    return result
Example #26
0
  def test_get_all_generic_methods_metadata(self):
    """get_all_generic_methods_metadata should return a list of all generic_methods with all defined metadata tags"""
    metadata = ncf.get_all_generic_methods_metadata()["data"]

    number_generic_methods = len(ncf.get_all_generic_methods_filenames())
    self.assertEquals(number_generic_methods, len(metadata))
Example #27
0
def get_technique_metadata_xml(technique_metadata,
                               include_rudder_reporting=False):
    """Get metadata xml for a technique as string"""

    # Get all generic methods
    generic_methods = ncf.get_all_generic_methods_metadata(
        alt_path='/var/rudder/configuration-repository/ncf'
    )['data']['generic_methods']

    content = []
    content.append('<TECHNIQUE name="' + technique_metadata['name'] + '">')
    content.append('  <DESCRIPTION>' + technique_metadata['description'] +
                   '</DESCRIPTION>')
    content.append('  <BUNDLES>')
    content.append('    <NAME>' + technique_metadata['bundle_name'] +
                   '</NAME>')
    if include_rudder_reporting:
        content.append('    <NAME>' + technique_metadata['bundle_name'] +
                       '_rudder_reporting</NAME>')
    content.append('  </BUNDLES>')

    if include_rudder_reporting:
        content.append('  <TMLS>')
        content.append('    <TML name="rudder_reporting"/>')
        content.append('  </TMLS>')

    content.append('  <FILES>')
    content.append(
        '    <FILE name="RUDDER_CONFIGURATION_REPOSITORY/ncf/50_techniques/' +
        technique_metadata['bundle_name'] + '/' +
        technique_metadata['bundle_name'] + '.cf">')
    content.append('      <INCLUDED>true</INCLUDED>')
    content.append('    </FILE>')
    content.append('  </FILES>')

    content.append('  <SECTIONS>')

    method_calls = technique_metadata["method_calls"]

    # Get all method call, with no duplicate values
    methods_name = set()
    for method_call in method_calls:
        # Expected reports for Rudder should not include any "meta" bundle calls (any beginning with _)
        if method_call['method_name'].startswith("_"):
            continue

        method_name = methods_name.add(method_call['method_name'])

    # For each method used, create a section containing all calls to that method
    methods_name_ordered = list(methods_name)
    methods_name_ordered.sort()
    section_list = []
    for method_name in methods_name_ordered:

        try:
            generic_method = generic_methods[method_name]
        except Exception as e:
            sys.stderr.write(
                "Error: The method '" + method_name +
                "' does not exist. Aborting Technique creation..." + "\n")
            sys.stderr.write(traceback.format_exc())
            exit(1)

        # Filter all method calls to get only those about that method
        filter_method_calls = [
            x for x in method_calls if x["method_name"] == method_name
        ]
        # Generare xml for that section
        section = generate_section_xml(filter_method_calls, generic_method)
        section_list.extend(section)

    content.extend(section_list)
    content.append('  </SECTIONS>')
    content.append('</TECHNIQUE>')

    # Join all lines with \n to get a pretty xml
    result = '\n'.join(content) + "\n"

    return result
Example #28
0
def generate_rudder_reporting(technique):
    """Generate complementary reporting needed for Rudder in rudder_reporting.st file"""
    # Get all generic methods
    generic_methods = ncf.get_all_generic_methods_metadata(
        alt_path='/var/rudder/configuration-repository/ncf'
    )['data']['generic_methods']

    content = []
    content.append('bundle agent ' + technique['bundle_name'] +
                   '_rudder_reporting')
    content.append('{')
    content.append('  vars:')
    content.append(
        '    "promisers"          slist => { @{this.callers_promisers}, cf_null }, policy => "ifdefined";'
    )
    content.append(
        '    "class_prefix"      string => canonify(join("_", "promisers"));')
    content.append('    "args"               slist => { };')
    content.append('')
    content.append('  methods:')

    # Handle method calls
    technique_name = technique['bundle_name']
    # Filter calls so we only have those who are not using a any class_context
    filter_calls = [
        method_call for method_call in technique["method_calls"]
        if method_call['class_context'] != "any"
    ]

    for method_call in filter_calls:

        method_name = method_call['method_name']
        generic_method = generic_methods[method_name]

        key_value = method_call["args"][generic_method["class_parameter_id"] -
                                        1].replace("\\'", "\'")
        regex = re.compile("[^\$\{\}a-zA-Z0-9_](?![^{}]+})|\$(?!{)")
        # to match cfengine behaviour we need to treat utf8 as if it was ascii (see #7195)
        # string should be unicode string (ie u'') which is the case if they are read from files opened with encoding="utf-8"
        key_value = key_value.encode("utf-8").decode("iso-8859-1")
        key_value_canonified = regex.sub("_", key_value)

        class_prefix = generic_method[
            "class_prefix"] + "_" + key_value_canonified
        logger_rudder_call = '"dummy_report" usebundle => log_rudder("' + generic_method[
            'name'] + ' ' + key_value + ' if ' + method_call[
                'class_context'] + '", "' + class_prefix + '", "${class_prefix}", @{args})'
        logger_rudder_call = logger_rudder_call.replace("&", "\\&")

        # Always add an empty line for readability
        content.append('')

        if not "$" in method_call['class_context']:
            content.append('    !(' + method_call['class_context'] + ')::')
            content.append(
                '      "dummy_report" usebundle => _classes_noop("' +
                class_prefix + '");')
            content.append('      ' + logger_rudder_call + ';')

        else:
            class_context = ncf.canonify_class_context(
                method_call['class_context'])

            content.append(
                '      "dummy_report" usebundle => _classes_noop("' +
                class_prefix + '"),')
            content.append('                    ifvarclass => concat("!(' +
                           class_context + ')");')
            content.append('      ' + logger_rudder_call + ',')
            content.append('                    ifvarclass => concat("!(' +
                           class_context + ')");')

    content.append('}')

    # Join all lines with \n to get a pretty CFEngine file
    result = '\n'.join(content) + "\n"

    return result
Example #29
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Test if the documentation fields contain unescaped dollar characters that would break pdflatex

import ncf
import re
import sys

from pprint import pprint

if __name__ == '__main__':

  # Get all generic methods
  generic_methods = ncf.get_all_generic_methods_metadata()["data"]["generic_methods"]
  test_file = sys.argv[0]
  
  check_backquotes = re.compile('[^\`]*\$[^\`]*')
  errors = 0
  
  for name, method in generic_methods.items():
    if "documentation" in method:
      if check_backquotes.match(method["documentation"]):
        print("Test "+name+" has non escaped $ in its documentation")
        errors += 1
  
  if errors == 0:
    print("R: "+test_file+" Pass")
  else:
    print("R: "+test_file+" FAIL")
Example #30
0
def generate_rudder_reporting(technique):
  """Generate complementary reporting needed for Rudder in rudder_reporting.st file"""
  # Get all generic methods
  generic_methods = ncf.get_all_generic_methods_metadata(alt_path='/var/rudder/configuration-repository/ncf')['data']['generic_methods']

  args = ""
  bundle_param = ""
  if len(technique["parameter"]) > 0:
    bundle_param = "("+", ".join([ncf.canonify(param["name"]) for param in technique["parameter"] ])+")"
    args = ", ".join('"${' +  ncf.canonify(param["name"]) + '}"' for param in technique["parameter"] )

  bundle_name = technique['bundle_name']+'_rudder_reporting'

  content = []
  content.append('bundle agent '+ technique['bundle_name']+'_rudder_reporting'+ bundle_param)
  content.append('{')
  content.append('  vars:')
  content.append('    "args"               slist => { '+ args +' };')
  content.append('    "report_param"      string => join("_", args);')
  content.append('    "full_class_prefix" string => canonify("' + bundle_name + '_${report_param}");')
  content.append('    "class_prefix"      string => string_head("${full_class_prefix}", "1000");')
  content.append('')
  content.append('  methods:')

  report_unique_id = 0

  for method_call in technique["method_calls"]:

    method_name = method_call['method_name']
    if method_call['method_name'].startswith("_"):
      continue
    generic_method = generic_methods[method_name]

    key_value = ncf.get_key_value(method_call, generic_method)

    class_prefix = '${class_prefix}_'+ncf.get_class_prefix(key_value, generic_method)
    method_reporting = '"dummy_report_' + str(report_unique_id) + '" usebundle => ' + ncf.generate_reporting_context(generic_method, method_call) 
    report_unique_id += 1
    class_parameter  = ncf.generate_reporting_class_parameter(generic_method, method_call)

    if not "cfengine-community" in generic_method["agent_support"]:

      message = "'"+generic_method["name"]+"' method is not available on cfengine based agent, skip"
      logger_call = get_logger_call(message, class_prefix, class_parameter)

      content.append('    any::')
      content.append('    "dummy_report" usebundle => _classes_noop("'+class_prefix+'");')
      content.append('    ' + method_reporting + ';')
      content.append('    ' + logger_call+';')

    elif method_call['class_context'] != "any":
      # escape double quote in key value
      regex_quote = re.compile(r'(?<!\\)"', flags=re.UNICODE )
      escaped_key_value = regex_quote.sub('\\"', key_value)

      message = generic_method['name'] + ' ' + escaped_key_value + ' if ' + method_call['class_context']
      logger_rudder_call = get_logger_call(message, class_prefix, class_parameter)

      # Always add an empty line for readability
      content.append('')

      if not "$" in method_call['class_context']:
        content.append('    !('+method_call['class_context']+')::')
        content.append('      "dummy_report" usebundle => _classes_noop("'+class_prefix+'");')
        content.append('      ' + method_reporting + ';')
        content.append('      ' + logger_rudder_call + ';')

      else:
        class_context = ncf.canonify_class_context(method_call['class_context'])

        content.append('      "dummy_report" usebundle => _classes_noop("'+class_prefix+'"),')
        content.append('                    ifvarclass => concat("!('+class_context+')");')
        content.append('      ' + method_reporting + ',')
        content.append('                    ifvarclass => concat("!('+class_context+')");')
        content.append('      ' + logger_rudder_call + ',')
        content.append('                    ifvarclass => concat("!('+class_context+')");')

  content.append('}')

  # Join all lines with \n to get a pretty CFEngine file
  result =  '\n'.join(content)+"\n"

  return result
Example #31
0
  
  cfengine_versions = list(min_version.keys())
  cfengine_versions.sort(key=StrictVersion)
  
  for cfengine_version in cfengine_versions:
    if StrictVersion(canonified_version) <= StrictVersion(cfengine_version):
      return min_version[cfengine_version]
  return False


if __name__ == '__main__':
  # Get CFEngine <=> Rudder versions
  versions = get_min_versions()

  # Get all generic methods
  generic_methods = ncf.get_all_generic_methods_metadata()["data"]["generic_methods"]
  
  categories = {}
  for method_name in sorted(generic_methods.keys()):
    category_name = method_name.split('_',1)[0]
    generic_method = generic_methods[method_name]
    if (category_name in categories):
      categories[category_name].append(generic_method)
    else:
      categories[category_name] = [generic_method]

  content = []

  for category in sorted(categories.keys()):
    content.append("\n*****\n")
    content.append('\n### '+category.title())
Example #32
0
def generate_rudder_reporting(technique):
    """Generate complementary reporting needed for Rudder in rudder_reporting.st file"""
    # Get all generic methods
    generic_methods = ncf.get_all_generic_methods_metadata(
        alt_path='/var/rudder/configuration-repository/ncf'
    )['data']['generic_methods']

    content = []
    content.append('bundle agent ' + technique['bundle_name'] +
                   '_rudder_reporting')
    content.append('{')
    content.append('  vars:')
    content.append(
        '    "promisers"          slist => { @{this.callers_promisers}, cf_null }, policy => "ifdefined";'
    )
    content.append(
        '    "class_prefix"      string => canonify(join("_", "promisers"));')
    content.append('    "args"               slist => { };')
    content.append('')
    content.append('  methods:')

    for method_call in technique["method_calls"]:

        method_name = method_call['method_name']
        if method_call['method_name'].startswith("_"):
            continue
        generic_method = generic_methods[method_name]

        key_value = ncf.get_key_value(method_call, generic_method)

        class_prefix = ncf.get_class_prefix(key_value, generic_method)

        if not "cfengine-community" in generic_method["agent_support"]:

            message = "'" + generic_method[
                "name"] + "' method is not available on cfengine based agent, skip"
            logger_call = ncf.get_logger_call(message, class_prefix)

            content.append('    any::')
            content.append('    "dummy_report" usebundle => _classes_noop("' +
                           class_prefix + '");')
            content.append('    ' + logger_call + ';')

        elif method_call['class_context'] != "any":
            # escape double quote in key value
            regex_quote = re.compile(r'(?<!\\)"', flags=re.UNICODE)
            escaped_key_value = regex_quote.sub('\\"', key_value)

            message = generic_method[
                'name'] + ' ' + escaped_key_value + ' if ' + method_call[
                    'class_context']
            logger_rudder_call = ncf.get_logger_call(message, class_prefix)

            # Always add an empty line for readability
            content.append('')

            if not "$" in method_call['class_context']:
                content.append('    !(' + method_call['class_context'] + ')::')
                content.append(
                    '      "dummy_report" usebundle => _classes_noop("' +
                    class_prefix + '");')
                content.append('      ' + logger_rudder_call + ';')

            else:
                class_context = ncf.canonify_class_context(
                    method_call['class_context'])

                content.append(
                    '      "dummy_report" usebundle => _classes_noop("' +
                    class_prefix + '"),')
                content.append('                    ifvarclass => concat("!(' +
                               class_context + ')");')
                content.append('      ' + logger_rudder_call + ',')
                content.append('                    ifvarclass => concat("!(' +
                               class_context + ')");')

    content.append('}')

    # Join all lines with \n to get a pretty CFEngine file
    result = '\n'.join(content) + "\n"

    return result
Example #33
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Usage: ./ncf_doc.py
#
# This is a Python module to generate documentation from generic methods in ncf

import ncf 

if __name__ == '__main__':

  # Get all generic methods
  generic_methods = ncf.get_all_generic_methods_metadata()
  
  
  categories = {}
  for method_name in sorted(generic_methods.iterkeys()):
    category_name = method_name.split('_',1)[0]
    generic_method = generic_methods[method_name]
    if (category_name in categories):
      categories[category_name].append(generic_method)
    else:
      categories[category_name] = [generic_method]
    


  content = []
  html_content = []

  content.append("Title: Reference")
  content.append("slugs: reference")