def generate2(targetFilePath, tmpl, model): ensureFolder(os.path.dirname(targetFilePath)) if isinstance(tmpl, jinja2.Template): try: result = tmpl.render(m=model) except jinja2.exceptions.TemplateRuntimeError as err: print '---------------------------------------------------------' traceback.print_exc(file=sys.stdout) print '---------------------------------------------------------' ERROR("Error in '{0}' file generation: {1}".format( targetFilePath, err.message)) else: result = tmpl with open(targetFilePath, "w") as f: f.write(result) if targetFilePath.endswith(".sh"): cp = stat.S_IMODE(os.lstat(targetFilePath).st_mode) os.chmod( targetFilePath, cp | stat.S_IXUSR | (stat.S_IXGRP if cp & stat.S_IRGRP else 0) | (stat.S_IXOTH if cp & stat.S_IROTH else 0)) logger.info("File '{0}' successfully generated as executable".format( targetFilePath)) else: logger.info("File '{0}' successfully generated".format(targetFilePath))
def dumpTmpl(self, fileName, tmplType, string): fname = os.path.join(self.folder, "tmpls", fileName + "." + tmplType) misc.ensureFolder(os.path.dirname(fname)) with open(fname, "w") as f: f.write(string)
def __init__(self, location, unsafe): self.folder = os.path.join(location, "dump") self.unsafe = unsafe misc.ensureFolder(self.folder)
def main(): global vaultFactory mydir = os.path.dirname(os.path.realpath(__file__)) parser = argparse.ArgumentParser() parser.add_argument('--src', required=True) parser.add_argument('--mark', choices=["none", "both", "start", "end"]) parser.add_argument('--dump', action='store_true') parser.add_argument('--dumpPasswords', action='store_true') parser.add_argument('--out') # Generate a file to set some variable param = parser.parse_args() loggingConfFile = os.path.join(mydir, "./logging.yml") logging.config.dictConfig( yaml.load(open(loggingConfFile), Loader=yaml.SafeLoader)) sourceFile = os.path.normpath(os.path.abspath(param.src)) if not os.path.isfile(sourceFile): ERROR("File '{}' does not exists".format(sourceFile)) logger.info("Will handle '{}'".format(sourceFile)) sourceFileDir = os.path.dirname(sourceFile) cluster = yaml.load(open(sourceFile), Loader=yaml.SafeLoader) targetFolder = misc.appendPath( sourceFileDir, cluster["build_folder"] if "build_folder" in cluster else "build") misc.ensureFolder(targetFolder) logger.info("Build folder: '{}'".format(targetFolder)) if "config_file" in cluster: baseConfigFile = cluster["config_file"] else: baseConfigFile = "ezconfig.yml" config, configFile = buildConfig(sourceFileDir, baseConfigFile) plugins = [] plugins.append(Plugin("core", misc.appendPath(mydir, "../plugins/core"))) logger.debug("Plugins path:'{}'".format(config[PLUGINS_PATH])) appendPlugins(plugins, cluster, config[PLUGINS_PATH]) schema = buildSchema(mydir, plugins) configSchema, safeConfigSchema = buildConfigSchema(mydir, config[PLUGINS_PATH]) if param.dump: dumper = Dumper(targetFolder, param.dumpPasswords) dumper.dump("schema.json", schema) dumper.dump("config-schema.json", configSchema) dumper.dump("safe-config-schema.json", safeConfigSchema) else: dumper = None k = kwalify(source_data=cluster, schema_data=schema) k.validate(raise_exception=False) if len(k.errors) != 0: ERROR("Problem {0}: {1}".format(sourceFile, k.errors)) k = kwalify(source_data=config, schema_data=configSchema) k.validate(raise_exception=False) if len(k.errors) != 0: ERROR("Configuration problem {0}: {1}".format(configFile, k.errors)) data = {} data['sourceFileDir'] = sourceFileDir data["targetFolder"] = targetFolder data['ezclusterHome'] = misc.appendPath(mydir, "..") data["rolePaths"] = set() data["configFile"] = configFile model = {} model['cluster'] = cluster model["config"] = config model['data'] = data initVault(model) if SAFE_CONFIG in model and safeConfigSchema != None: k = kwalify(source_data=model[SAFE_CONFIG], schema_data=safeConfigSchema) k.validate(raise_exception=False) if len(k.errors) != 0: ERROR("Configuration problem {0}: {1}".format( model["data"][_SAFE_CONFIG_FILE_], k.errors)) for plugin in plugins: plugin.groom(model) for plugin in plugins: plugin.groom2(model) targetFileByName = buildTargetFileByName(plugins) if param.dump: dumper.dump("cluster.json", model['cluster']) dumper.dump("data.json", model['data']) dumper.dump("targetFileByName.json", targetFileByName) dumper.dump("config.json", config) if SAFE_CONFIG in model and dumper.unsafe: dumper.dump("safeConfig.json", model[SAFE_CONFIG]) for plugin in plugins: plugin.dump(model, dumper) generate(targetFileByName, targetFolder, model, param.mark, dumper) if "out" in param: f = open(param.out, "w+") f.write("# Generated by ezcluster:\n") if "buildScript" in model["data"]: f.write('BUILD_SCRIPT="{}"\n'.format(model["data"]["buildScript"])) f.close()
def main(): mydir = os.path.dirname(os.path.realpath(__file__)) parser = argparse.ArgumentParser() parser.add_argument('--src', nargs='*', required=True) parser.add_argument('--action', required=True) parser.add_argument('--scope', nargs='*', required=False) parser.add_argument('--noScope', nargs='*', required=False) parser.add_argument('--yamlLoggingConf', help="Logging configuration as a yaml file", required=False) parser.add_argument('--workingFolder', help="Where to store working context", required=True) param = parser.parse_args() if param.yamlLoggingConf != None: loggingConfFile = param.yamlLoggingConf else: loggingConfFile = os.path.join(mydir, "conf/logging.yml") if not os.path.isfile(loggingConfFile): misc.ERROR("'{0}' is not a readable file!".format(loggingConfFile)) logging.config.dictConfig(yaml.load(open(loggingConfFile))) logger.debug("mydir:" + mydir) logger.debug("param.src:" + str(param.src)) workingFolder = param.workingFolder if not os.path.isdir(workingFolder): misc.ERROR("{0} must be an existing folder".format(workingFolder)) if len(os.listdir(workingFolder)) > 0: misc.ERROR("{0} must be an existing EMPTY folder".format(workingFolder)) # ----- We must make a first read of the file, with only the 'master' plugin to fetch plugins list and path masterPluginPath = os.path.abspath(os.path.join(mydir, ".")) context = Context(workingFolder) context.loadPlugin("master", [masterPluginPath]) handleSourceFiles(param.src, context, None) context.groom() # --------------------------------------------- included scope handling context.includedScopes = handleCliScopes(param.scope) if len(context.includedScopes) == 0 and INCLUDED_SCOPES in context.model[SRC]: context.includedScopes = set(context.model[SRC][INCLUDED_SCOPES]) if len(context.includedScopes) > 0: print("Scope limited to {0}".format(str(list(context.includedScopes)))) # -------------------------------------------- Excluded scope handling context.excludedScopes = handleCliScopes(param.noScope) if EXCLUDED_SCOPES in context.model[SRC]: context.excludedScopes = context.excludedScopes.union(context.model[SRC][EXCLUDED_SCOPES]) if len(context.excludedScopes) > 0: print("Scope excluded: {0}".format(str(list(context.excludedScopes)))) # Now, we must have the effective PLUGINS list and PLUGINS_PATHS in the context. We can load all plugins for plName in context.model[SRC][PLUGINS]: context.loadPlugin(plName, context.model[SRC][PLUGINS_PATHS]) # And reload source files, with now all plugins activated fileByVariable = {} if param.action == "dumpvars" else None handleSourceFiles(param.src, context, fileByVariable) if 'include' in context.model[SRC]: del(context.model[SRC]['include']) # Must remove, as not part of the schema # Now, build the schema for source validation, by merge of all schema plugin theSchema = context.getSchema() dump.dumpSchema(context, theSchema) #dump.dumpModel(context) # And validate against this schema schema.validate(context.model[SRC], theSchema) # And groom all plugins context.groom() dump.dumpModel(context) # Check scopes validity # NB: We perform this after grooming, even if grooming can rely on scope. Aims is only to detect scopes with typo. supportedScopes = context.getAllSupportedScopes() scopesToTest = context.excludedScopes.union(context.includedScopes) for scope in scopesToTest: if scope != "all" and scope != "none" and not context.checkScope(scope) and scope not in supportedScopes: # checkScope(): Scope for target file/folders (hosts and hostgroups) misc.ERROR("Scope '{0}' is not supported!".format(scope)) templator = Templator([os.path.join(mydir, './templates'), context.workingFolder], context.model) actions = context.getAllSupportedActions() logger.debug("Supported actions: {0}".format(actions)) action = param.action if action == "none": for action in actions: pluginExts = context.getPluginExtForAction(action) logger.debug("Action: {0} -> plugins: {1}".format(action, pluginExts)) context.buildTemplate(action, pluginExts) context.builRolesPath(action, pluginExts) context.generateAuxTemplates(action, pluginExts) templator.generate("{0}.yml.jj2".format(action), os.path.join(context.workingFolder, "{0}.yml".format(action))) elif action == "dumpvars": if SRC in context.model and VARS in context.model[SRC]: print("---") variables = context.model[SRC][VARS] for name in sorted(variables): x = yaml.dump(variables[name], default_flow_style=True, default_style=None, explicit_end=False) p = x.find("\n...\n") if p > 0: x = x[:-5] p = x.find("\n") if p > 0: x = x[:-1] print("{}: {} ({})".format(name, x, fileByVariable[name] if name in fileByVariable else "??")) print("---") #txt = yaml.dump(context.model[SRC][VARS], default_flow_style=False, default_style=None) return else: if not action in actions: misc.ERROR("Action {0} not supported. Current configuration only supports {1}".format(action, str(actions))) pluginExts = context.getPluginExtForAction(action) logger.debug("Action: {0} -> plugins: {1}".format(action, pluginExts)) context.buildTemplate(action, pluginExts) context.builRolesPath(action, pluginExts) context.generateAuxTemplates(action, pluginExts) templator.generate("{0}.yml.jj2".format(action), os.path.join(context.workingFolder, "{0}.yml".format(action))) templator.generate("inventory.jj2", os.path.join(context.workingFolder, "inventory")) templator.generate("ansible.cfg.jj2", os.path.join(context.workingFolder, "ansible.cfg")) misc.ensureFolder(os.path.join(context.workingFolder, "group_vars")) templator.generate("group_vars_all.jj2", os.path.join(context.workingFolder, "group_vars/all"))