forked from Normation/ncf
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b8e3cc3
commit b91c5b1
Showing
3 changed files
with
256 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
import unittest | ||
import ncf | ||
import ncf_constraints | ||
import ncf_dsc | ||
import os.path | ||
import subprocess | ||
import shutil | ||
from pprint import pprint | ||
|
||
class TestNcf(unittest.TestCase): | ||
|
||
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"] | ||
|
||
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.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' }, | ||
] | ||
} | ||
|
||
|
||
##################################### | ||
# Tests for writing/delete Techniques all metadata info | ||
##################################### | ||
|
||
def test_generate_technique_content(self): | ||
"""Test if content from a valid technique generated a valid CFEngine file as expected""" | ||
|
||
# Join all lines with \n to get a pretty technique file | ||
generated_result = ncf_dsc.get_ps1_content(self.technique_metadata, self.all_methods) | ||
|
||
print(generated_result) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
# | ||
# Usage: ./ncf_rudder.py path | ||
# | ||
# This is a Python module containing functions to generate technique for Rudder from ncf techniques | ||
# | ||
# This module is designed to run on the latest major versions of the most popular | ||
# server OSes (Debian, Red Hat/CentOS, Ubuntu, SLES, ...) | ||
# At the time of writing (November 2013) these are Debian 7, Red Hat/CentOS 6, | ||
# Ubuntu 12.04 LTS, SLES 11, ... | ||
# The version of Python in all of these is >= 2.6, which is therefore what this | ||
# module must support | ||
|
||
import os.path | ||
import ncf | ||
import sys | ||
import re | ||
import codecs | ||
import traceback | ||
from pprint import pprint | ||
|
||
# MAIN FUNCTIONS called by command line parsing | ||
############################################### | ||
|
||
def write_all_techniques_for_rudder(root_path): | ||
write_category_xml(root_path) | ||
techniques = ncf.get_all_techniques_metadata(alt_path='/var/rudder/configuration-repository/ncf')['data']['techniques'] | ||
ret = 0 | ||
for technique, metadata in techniques.items(): | ||
try: | ||
write_technique_for_rudder(root_path, metadata) | ||
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) | ||
|
||
|
||
def convert_to_dsc(destination_path, bundle_name): | ||
techniques = ncf.get_all_techniques_metadata(alt_path='/var/rudder/configuration-repository/ncf')['data']['techniques'] | ||
if bundle_name in techniques.keys(): | ||
try: | ||
metadata = techniques[bundle_name] | ||
write_technique_for_rudder(destination_path, metadata) | ||
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) | ||
|
||
|
||
def bundle_name_to_dsc(bundle_name): | ||
return "-".join([ part.capitalize() for part in bundle_name.split("_") ]) | ||
|
||
def param_name_to_dsc(param_name): | ||
return "".join([ part.capitalize() for part in param_name.split("_") ]) | ||
|
||
def get_ps1_content(technique_metadata, generic_methods): | ||
|
||
pprint(technique_metadata) | ||
content = [] | ||
content.append("function "+ technique_metadata["bundle_name"] +" {") | ||
content.append(" [CmdletBinding()]") | ||
content.append(" param (") | ||
content.append(" [parameter(Mandatory=$true)]") | ||
content.append(" [string]$reportIdentifier,") | ||
content.append(" [parameter(Mandatory=$true)]") | ||
content.append(" [string]$techniqueName,") | ||
content.append(" [switch]$auditOnly") | ||
content.append(" )") | ||
content.append("") | ||
content.append(" $local_classes = New-ClassContext") | ||
content.append("") | ||
|
||
generic_params = " -reportIdentifier $reportIdentifier -techniqueName $techniqueName -auditOnly:$auditOnly)" | ||
for method_call in technique_metadata["method_calls"]: | ||
|
||
|
||
params = [ param_name_to_dsc(param) for param in generic_methods[method_call["method_name"]]["bundle_args"] ] | ||
|
||
pprint(params) | ||
method_params = " ".join( [ "-"+params[ind]+" '"+value+"'" for ind, value in enumerate(method_call["args"]) ]) | ||
|
||
pprint(method_params) | ||
|
||
dsc_bundle_name = bundle_name_to_dsc(method_call["method_name"]) | ||
call = "$local_classes = Merge-ClassContext $local_classes $("+dsc_bundle_name+" "+method_params+generic_params | ||
if method_call['class_context'] != "any": | ||
content += " $class = \""+method_call['class_context']+"\"" | ||
|
||
content += " if (Evaluate-Class $class $local_classes $system_classes) {" | ||
content += " "+call | ||
content += " } else {" | ||
componentName = generic_methods[method_call['method_name']]["name"] | ||
content += " _rudder_common_report_na -componentName '"+componentName+"' -componentKey '"+method_call["class_parameter"]+"' -message 'Not applicable'"+generic_params | ||
content += " }" | ||
content += "" | ||
else: | ||
content.append(" "+call) | ||
content.append("}") | ||
|
||
|
||
return "\n".join(content) | ||
|
||
|
||
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="'+escape_entities(technique_metadata['name'])+'">') | ||
content.append(' <DESCRIPTION>'+escape_entities(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(' <FILE name="'+technique_metadata['bundle_name']+'.ps1">') | ||
content.append(' <INCLUDED>false</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 | ||
|
||
|
||
def usage(): | ||
sys.stderr.write("Can't parse parameters\n") | ||
print("Usage: ncf_rudder <command> [arguments]") | ||
print("Available commands:") | ||
print(" - canonify_expected_reports <source file> <destination file>") | ||
print(" - rudderify_techniques <destination path>") | ||
print(" - rudderify_technique <destination path> <bundle_name>") | ||
|
||
|
||
if __name__ == '__main__': | ||
|
||
if len(sys.argv) <= 1: | ||
usage() | ||
exit(1) | ||
|
||
if sys.argv[1] == "convert_to_dsc": | ||
convert_to_dsc(sys.argv[2],sys.argv[3]) | ||
elif sys.argv[1] == "rudderify_techniques": | ||
write_all_techniques_for_rudder(sys.argv[2]) | ||
elif sys.argv[1] == "rudderify_technique": | ||
write_one_technique_for_rudder(sys.argv[2],sys.argv[3]) | ||
else: | ||
usage() | ||
exit(1) |