def config(ctx, directory: str, template_dir: str, template: str, filename: str, overwrite: bool): """Command that will create a project config file that can be used to supply additional information for the documentation generation process.""" try: # Set the directory path based on either the passed directory arg, or the click context. path = SetPath(directory, ctx) # Gather the project variables to construct the object that the template will use to generate the config file. # Set the type of provider class to call if ctx.obj.get('provider').lower() == 'terraform' or ctx.obj.get('provider') == 'tf': Variables = TFDoc(path).BuildVarList() log.debug("Variable list retrieved from provided file path...") # Load, render and write the Jinja Template log.debug("Attempting to build project config file...") ConfigFile = Jinja(TemplateDir=template_dir, Template=template, OutputDir=path, OutputFile=filename) ConfigFile.LoadTemplate() ConfigFile.RenderTemplate(Variables) ConfigFile.WriteTemplate(Overwrite=overwrite) # Add the Dir Tree Variable to the Template Dictionary: cprint("Config file successfully written to: {}".format(os.path.join(path, filename))) except Exception as e: cprint(" ERROR ENCOUNTERED: ", 'grey', 'on_red') cprint("Error: Failed to complete config file creation", 'red') cprint(str(e), 'red') log.error("Error: Failed to complete config file creation") log.error(str(e)) raise sys.exit()
def release(ctx, namespace: str, repo: str, directory: str, token: str): """Command that will retrieve the project repository information from the projects configured GIT repository.""" try: # Set the directory path based on either the passed directory arg, or the click context. path = SetPath(directory, ctx) # If the namespace and repository were provided, then assign the values, if not check for .git/config file and parse. if repo is not None and namespace is not None: RequestObj = Github(namespace, repo, token).GetLatestRelease() # Try and fetch the repository URL from the configured directory. elif os.path.exists("{}/.git/config".format(path)): namespace, repo = ParseRepoUrl(path) RequestObj = Github(namespace, repo, token).GetLatestRelease() else: RequestObj = "Undefined" print("Latest Release: {}".format(RequestObj)) except Exception as e: cprint(" ERROR ENCOUNTERED: ", 'grey', 'on_red') cprint( "Warning: Failed to retrieve GIT repository release data for the targeted project.", 'red') cprint(str(e), 'red') log.error( "Warning: Failed to retrieve GIT repository release data for the targeted project. Check the provided namespace and repo settings and try again." ) log.error(str(e)) sys.exit()
def files(ctx, subdir: bool, directory: str): """Command that will retrieve a list of files from a target directory location matching the provider type specified (terraform = .tf)""" try: # Set the directory path based on either the passed directory arg, or the click context. path = SetPath(directory, ctx) # Set the type of provider class to call if ctx.obj.get('provider').lower() == 'terraform' or ctx.obj.get( 'provider') == 'tf': Files = TFDoc(path, subdir).FetchFileList() log.debug("File list retrieved from provided file path...") # Print command results. cprint( "{} {} files found in target directory: {}".format( len(Files), ctx.obj.get('provider').lower(), path), 'green') # Print the results for item in Files: # For the command output remove the base path specified as its redundant item = item.replace("{}/".format(path), "") # Call SplitPath to find found results in subdirectories. item_path_list = SplitPath(item) # Print results if not item_path_list[0]: cprint(item_path_list[1], 'white') log.debug(item_path_list[1]) else: print(colored("/{} =>".format(item_path_list[0]), 'blue'), colored(item_path_list[1], 'white')) log.debug("{} => {}".format(item_path_list[0], item_path_list[1])) print("\n") except Exception as e: cprint(" ERROR ENCOUNTERED: ", 'grey', 'on_red') cprint( "Error: Failed to retrieve file list from the provided file path location, check the provided file path and try again", 'red') cprint(str(e), 'red') log.error( "Error: Failed to retrieve file list from the provided file path location, check the provided file path and try again" ) log.error(str(e)) sys.exit()
def dirtree(ctx, directory: str): """Command that will create an ascii directory tree listing that can be used within the generated documentation.""" try: # Set the directory path based on either the passed directory arg, or the click context. path = SetPath(directory, ctx) log.debug("Attempting to build directory tree variable...") # Set a variable for the Directory tree, and then call the Directory Tree Generator FileTree = DirTree(path) # Add the Dir Tree Variable to the Template Dictionary: print(FileTree) except Exception as e: cprint(" ERROR ENCOUNTERED: ", 'grey', 'on_red') cprint("Error: Failed to build directory structure tree", 'red') cprint(str(e), 'red') log.error("Error: Failed to build directory structure tree") log.error(str(e)) sys.exit()
def outputs(ctx, subdir: bool, directory: str): """Command that will retrieve a list of all of the project outputs from the specified project path.""" try: # Set the directory path based on either the passed directory arg, or the click context. path = SetPath(directory, ctx) # Set the type of provider class to call if ctx.obj.get('provider').lower() == 'terraform' or ctx.obj.get( 'provider') == 'tf': Outputs = TFDoc(path, subdir).BuildOutputList() log.debug("Variable list retrieved from provided file path...") # Print Outputs. cprint( "{} {} outputs found in target project: {}".format( len(Outputs), ctx.obj.get('provider').lower(), path), 'green') # To make the print format uniform, cycle through the outputs object and get a max length to use for an offset value. Output_MaxLength = 0 for output in Outputs: if len(output.get('Name')) > Output_MaxLength: Output_MaxLength = len(output.get('Name')) # Print Outputs: for output in Outputs: offset = Output_MaxLength - len(output.get('Name')) print( colored("{}{} =".format(output.get('Name'), " " * offset), 'blue'), colored(str(output.get('OutputValue')), 'green')) print("\n") except Exception as e: cprint(" ERROR ENCOUNTERED: ", 'grey', 'on_red') cprint( "Error: Failed to retrieve output list from the provided file path location, check the provided file path and try again", 'red') cprint(str(e), 'red') log.error( "Error: Failed to retrieve outputs list from the provided file path location, check the provided file path and try again" ) log.error(str(e)) raise sys.exit()
def readme(ctx, directory: str, template_dir: str, template: str, filename: str, configfile: str, overwrite: bool, backup: bool, namespace: str, repo: str, token: str): """Command that will create a project readme.md for a repository .""" try: # Define the dictionary object that will be passed to the readme template. ReadmeObj = {} # Set the directory path based on either the passed directory arg, or the click context. path = SetPath(directory, ctx) # Call the config parser to parse a config file if one exists within the target directory. ReadmeConfig = Config(path, configfile) # print(json.dumps(ReadmeConfig.config, indent=4, sort_keys=True)) ReadmeObj.update(git=ReadmeConfig.config.get('GitConfig', {})) ReadmeObj.update(readme=ReadmeConfig.config.get('ReadMeConfig', {})) # Gather the project variables to construct the object that the template will use to generate the readme document. # Set the type of provider class to call if ctx.obj.get('provider').lower() == 'terraform' or ctx.obj.get('provider') == 'tf': Variables = TFDoc(path).BuildVarList() log.debug("Variable list retrieved from provided file path...") ReadmeObj.update(variables=Variables) # Add the required and optional images ReadMeObjVar = ReadmeObj.get('variables') ReadMeObjVar.update(required_image=ReadmeConfig.config.get('VariablesConfig').get('Required').get('Image')) ReadMeObjVar.update(optional_image=ReadmeConfig.config.get('VariablesConfig').get('Optional').get('Image')) # Gather the project outputs to use to construct the object that the template will use to generate the readme document. Outputs = TFDoc(path).BuildOutputList() log.debug("Output list retrieved from provided file path...") ReadmeObj.update(outputs=Outputs) # Graph the things GraphImage = TFDoc(path).BuildGraph() if GraphImage != "None": ReadmeObj.update(tfdiagram=GraphImage) # Update the variable objects with the data from the config pull ReadmeConfig.UpdateVars(ReadmeObj) log.info("ReadmeObj has been updated with variable data from the parsed config.") # print(json.dumps(ReadmeObj, indent=4, sort_keys=True)) # Add the Build Tree BuildTree = DirTree(path) log.debug("Dirtree created:\n{}".format(BuildTree)) ReadmeObj.update(tree=BuildTree) # Last attempt to fetch GitRepo Data and add it to the ReadMeObj before we generate the documentation. # If the namespace and repository were provided, then assign the values, if not check for .git/config file and parse. # Set variables to hold the Namespace and Repo GitNameSpace = None GitRepo = None # Try and use the variables first if repo is not None and namespace is not None: GitNameSpace = namespace GitRepo = repo log.debug("Configuring Git NameSpace and Repo from command variables...") log.debug("GitNameSpace set to value: {}".format(namespace)) log.debug("GitRepo set to value: {}".format(repo)) # Try and fetch the repository URL from the configured directory. elif isinstance(ReadmeObj.get('git'), dict): GitNameSpace = ReadmeObj.get('git').get('NameSpace') GitRepo = ReadmeObj.get('git').get('Name') log.debug("Configuring Git NameSpace and Repo from the project config file...") log.debug("GitNameSpace set to value: {}".format(ReadmeObj.get('git').get('NameSpace'))) log.debug("GitRepo set to value: {}".format(ReadmeObj.get('git').get('Name'))) elif os.path.exists("{}/.git/config".format(path)): GitNameSpace, GitRepo = ParseRepoUrl(path) log.debug("Configuring Git NameSpace and Repo from the project .git/config file...") log.debug("GitNameSpace set to value: {}".format(GitNameSpace)) log.debug("GitRepo set to value: {}".format(GitRepo)) # Attempt to make the call to the repository to fetch repo and release data. log.debug("Attempting to make request from Github...") if GitNameSpace is not None and GitRepo is not None: RequestObj = Github(GitNameSpace, GitRepo, token).GetGitHubData() log.debug("Git Repository Request State: {}".format(RequestObj)) if RequestObj.get('state') != "fail": ReadmeObj.update(repo=RequestObj) log.debug("Template Object has been updated to include the repository response object.") log.info("Generation of template dictionary object completed: {}".format(json.dumps(ReadmeObj, indent=4, sort_keys=True))) # Load, render and write the Jinja Template log.debug("Attempting to build project config file...") DocTemplate = Jinja(TemplateDir=template_dir, Template=template, OutputDir=path, OutputFile=filename) DocTemplate.LoadTemplate() DocTemplate.RenderTemplate(ReadmeObj) DocTemplate.WriteTemplate(Overwrite=overwrite, Backup=backup) # Add the Dir Tree Variable to the Template Dictionary: cprint("Template file successfully written to: {}".format(os.path.join(path, filename))) except Exception as e: cprint(" ERROR ENCOUNTERED: ", 'grey', 'on_red') cprint("Error: Failed to complete config file creation", 'red') cprint(str(e), 'red') log.error("Error: Failed to complete config file creation") log.error(str(e)) raise sys.exit()
def variables(ctx, subdir: bool, directory: str): """Command that will retrieve a list of all of the project variables from the specified project path.""" try: # Set the directory path based on either the passed directory arg, or the click context. path = SetPath(directory, ctx) # Set the type of provider class to call if ctx.obj.get('provider').lower() == 'terraform' or ctx.obj.get( 'provider') == 'tf': Variables = TFDoc(path, subdir).BuildVarList() log.debug("Variable list retrieved from provided file path...") # Print Required Variable Results. cprint( "{} {} required variables found in target project: {}".format( len(Variables.get('required_vars')), ctx.obj.get('provider').lower(), path), 'green') for reqvar in Variables.get('required_vars', []): offset = Variables.get('required_vars_maxlength') - len( reqvar.get('Name')) print( colored("{}{} =".format(reqvar.get('Name'), " " * offset), 'blue'), colored("Value Required", 'green')) print("\n") # Print Optional Variable Results. cprint( "{} {} optional variables found in target project: {}".format( len(Variables.get('optional_vars')), ctx.obj.get('provider').lower(), path), 'green') for optvar in Variables.get('optional_vars', []): offset = Variables.get('optional_vars_maxlength') - len( optvar.get('Name')) # Try to make the output nice and pretty, but if it fails, then default to normal print try: if 'list' in optvar.get('Type') and len( optvar.get('DefaultValue')) > 0: print( colored( "{}{} =".format(optvar.get('Name'), " " * offset), 'blue'), colored('[', 'green')) for item in optvar.get('DefaultValue'): if isinstance(item, dict): cprint(json.dumps(item, indent=4, sort_keys=True), 'green') else: cprint(" {}".format(item), 'green') cprint(']', 'green') elif 'map' in optvar.get('Type'): print( colored( "{}{} =".format(optvar.get('Name'), " " * offset), 'blue'), colored( json.dumps(optvar.get('DefaultValue'), indent=4, sort_keys=True), 'green')) else: print( colored( "{}{} =".format(optvar.get('Name'), " " * offset), 'blue'), colored(optvar.get('DefaultValue'), 'green')) except Exception: print( colored("{}{} =".format(optvar.get('Name'), " " * offset), 'blue'), colored(optvar.get('DefaultValue'), 'green')) print("\n") except Exception as e: cprint(" ERROR ENCOUNTERED: ", 'grey', 'on_red') cprint( "Error: Failed to retrieve variable list from the provided file path location, check the provided file path and try again", 'red') cprint(str(e), 'red') log.error( "Error: Failed to retrieve variable list from the provided file path location, check the provided file path and try again" ) log.error(str(e)) sys.exit()