From dc8c40d604a9604e05f0bf80c9545d6e336d342e Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Mon, 27 May 2019 14:22:44 -0400 Subject: [PATCH 01/27] Added -u, --undo flag --- kcleaner.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kcleaner.py b/kcleaner.py index 0661457..771b696 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -107,6 +107,11 @@ def remove_resource(config_file, removing_type): '--name', '-n', help='Name of the entry to remove', ) +@click.option( + '-u', '--undo', + help='Use this to roll back latest changes', + is_flag=True +) def cli(resource, name, kubeconfig): """ A little CLI tool to help keeping Config Files clean :) From 9555d334a36f0ec191edf4e863c5ec1a0bb37a64 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Mon, 27 May 2019 14:23:01 -0400 Subject: [PATCH 02/27] Removed check that was useless --- kcleaner.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/kcleaner.py b/kcleaner.py index 771b696..c85cecb 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -117,8 +117,6 @@ def cli(resource, name, kubeconfig): A little CLI tool to help keeping Config Files clean :) """ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') - if resource == None: - resource = "clusters" logging.debug(f'Using resource {resource}') logging.debug(f'Config file to use: {kubeconfig}') if name == None: From d235ff28ae3b1c30d898df830486ce63a4a37f3a Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Mon, 27 May 2019 14:23:54 -0400 Subject: [PATCH 03/27] Better order to read --- kcleaner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kcleaner.py b/kcleaner.py index c85cecb..3f1583e 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -108,7 +108,7 @@ def remove_resource(config_file, removing_type): help='Name of the entry to remove', ) @click.option( - '-u', '--undo', + '--undo', '-u', help='Use this to roll back latest changes', is_flag=True ) From 7ee1b603e8b746c9f7ac517d3c986e8962e8832a Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Mon, 27 May 2019 14:28:22 -0400 Subject: [PATCH 04/27] Added logic to read from .bak file --- kcleaner.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/kcleaner.py b/kcleaner.py index 3f1583e..dc3256b 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -112,11 +112,19 @@ def remove_resource(config_file, removing_type): help='Use this to roll back latest changes', is_flag=True ) -def cli(resource, name, kubeconfig): +def cli(resource, name, kubeconfig, undo): """ A little CLI tool to help keeping Config Files clean :) """ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + if undo: + logging.debug(f"Undo flag was set! checking for the backup file...") + kubeconfig_backup = f"{kubeconfig}.bak" + config_file = get_file(kubeconfig_backup) + else: + config_file = get_file(kubeconfig) + config_file = remove_resource(config_file, resource) + logging.debug(f'Using resource {resource}') logging.debug(f'Config file to use: {kubeconfig}') if name == None: @@ -124,10 +132,6 @@ def cli(resource, name, kubeconfig): else: logging.debug(f'Name of the resource requested to remove: {name}') - config_file = get_file(kubeconfig) - config_file = remove_resource(config_file, resource) - - update_file(kubeconfig, config_file) if __name__ == '__main__': From a3a1293f3cdc94fc84fc3f2a92e5232ea99deaa5 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Mon, 27 May 2019 14:31:19 -0400 Subject: [PATCH 05/27] Adding some feedback --- kcleaner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/kcleaner.py b/kcleaner.py index dc3256b..7bb040d 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -120,6 +120,7 @@ def cli(resource, name, kubeconfig, undo): if undo: logging.debug(f"Undo flag was set! checking for the backup file...") kubeconfig_backup = f"{kubeconfig}.bak" + print(f'Searching for backup config file {kubeconfig_backup}') config_file = get_file(kubeconfig_backup) else: config_file = get_file(kubeconfig) From 1457c6313a16f5625a3e06d94bdb6355b1b4ebf1 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Mon, 27 May 2019 14:33:26 -0400 Subject: [PATCH 06/27] Backing up before doing anything --- kcleaner.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kcleaner.py b/kcleaner.py index 7bb040d..7d1c9d5 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -117,13 +117,16 @@ def cli(resource, name, kubeconfig, undo): A little CLI tool to help keeping Config Files clean :) """ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + kubeconfig_backup = f"{kubeconfig}.bak" + if undo: logging.debug(f"Undo flag was set! checking for the backup file...") - kubeconfig_backup = f"{kubeconfig}.bak" print(f'Searching for backup config file {kubeconfig_backup}') config_file = get_file(kubeconfig_backup) else: config_file = get_file(kubeconfig) + logging.debug(f'Backing up config file at {kubeconfig_backup} before doing anything') + update_file(kubeconfig_backup, config_file) config_file = remove_resource(config_file, resource) logging.debug(f'Using resource {resource}') From 34c51c53b8c268373202b18692b1f42383d701a0 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Mon, 27 May 2019 14:59:16 -0400 Subject: [PATCH 07/27] Changed the way to view logs and exceptions --- kcleaner.py | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/kcleaner.py b/kcleaner.py index 7d1c9d5..80cd79a 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -26,7 +26,7 @@ def update_file(filename, yamldoc): logging.debug("Dumping new yaml doc into the config file") yaml.dump(yamldoc, stream) except yaml.YAMLError as exc: - print(exc) + logging.exception("Exception occured while trying to write Yaml file") def get_file(filename): logging.debug(f'Trying to retrieve contents of file {filename}') @@ -35,14 +35,14 @@ def get_file(filename): try: config_file = yaml.safe_load(stream) except yaml.YAMLError as exc: - print(exc) + logging.exception("Exception occured while trying to load Yaml file") logging.debug(f'File Contents\n{config_file}') logging.debug(f'Type of the file contents: {type(config_file)}') if config_file == None: - print("Config File is empty! Can't use it.") + logging.error("Config File is empty! Can't use it.") exit(11) elif type(config_file) == str: - print("Config File is not a valid yaml file!") + logging.error("Config File is not a valid yaml file!") exit(12) return config_file @@ -52,7 +52,7 @@ def test_file_exists(filename): if exists: logging.debug("File exists!") else: - print('Config File Not found!') + logging.error('Config File Not found!') # Keep presets exit(10) @@ -68,7 +68,7 @@ def remove_resource(config_file, removing_type): resources_to_remove = (iterfzf(resources_name_list, multi=True)) logging.debug('List of resources selected: {resources_to_remove}') if resources_to_remove == None: - print("No resources to remove selected!") + logging.error("No resources to remove selected!") exit() logging.debug(f"{len(config_file[removing_type])} {removing_type} before the removal") @@ -81,12 +81,14 @@ def remove_resource(config_file, removing_type): logging.debug('Removing resources...') config_file[removing_type] = [item for item in config_file[removing_type] if item['name'] not in resources_to_remove] except KeyError: - print(f"Something went wrong!!") + logging.exception(f"Something went wrong!!") logging.debug(f"{len(config_file[removing_type])} {removing_type} in the end") return config_file +def write_file(filename, yamldoc): + logging.info("Not Implemented Yet") @click.command() @click.argument( @@ -101,8 +103,9 @@ def remove_resource(config_file, removing_type): default='contexts' ) @click.option( - '--kubeconfig', '-k', default=f'{Path.home()}/.kube/config' - ) + '--kubeconfig', '-k', default=f'{Path.home()}/.kube/config', + help="path to the config file to clean" +) @click.option( '--name', '-n', help='Name of the entry to remove', @@ -112,29 +115,38 @@ def remove_resource(config_file, removing_type): help='Use this to roll back latest changes', is_flag=True ) -def cli(resource, name, kubeconfig, undo): +@click.option( + '--debug', '-d', + help='Use this to see debug level messages', + is_flag=True +) +def cli(resource, name, kubeconfig, undo, debug): """ A little CLI tool to help keeping Config Files clean :) """ - logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + if debug: + logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') + else: + logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s') + kubeconfig_backup = f"{kubeconfig}.bak" if undo: - logging.debug(f"Undo flag was set! checking for the backup file...") + logging.info(f"Undo flag was set! checking for the backup file...") print(f'Searching for backup config file {kubeconfig_backup}') config_file = get_file(kubeconfig_backup) else: config_file = get_file(kubeconfig) - logging.debug(f'Backing up config file at {kubeconfig_backup} before doing anything') + logging.info(f'Backing up config file at {kubeconfig_backup} before doing anything') update_file(kubeconfig_backup, config_file) config_file = remove_resource(config_file, resource) - logging.debug(f'Using resource {resource}') + logging.info(f'Using resource {resource}') logging.debug(f'Config file to use: {kubeconfig}') if name == None: - logging.debug(f'Name is empty, using fzf to search for the resource to remove') + logging.info(f'Name is empty, using fzf to search for the resource to remove') else: - logging.debug(f'Name of the resource requested to remove: {name}') + logging.info(f'Name of the resource requested to remove: {name}') update_file(kubeconfig, config_file) From 88aa5f4da369819ac6e94c9d45440c082ed3cd8e Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Tue, 28 May 2019 18:20:26 -0400 Subject: [PATCH 08/27] Added Some tests for the empty backup file --- kcleaner.py | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/kcleaner.py b/kcleaner.py index 80cd79a..cf3e6ec 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -20,17 +20,21 @@ def ask_yn(yn_question, default='n'): def update_file(filename, yamldoc): test_file_exists(filename) - logging.debug("Opening write stream for file {filename}") + if not test_file_exists(filename) and not "bak" in filename: + logging.error("Cannot work with an empty file!, please check the path of your config file.") + logging.debug(f"Opening write stream for file {filename}") with open(filename, 'w') as stream: try: - logging.debug("Dumping new yaml doc into the config file") + logging.debug("Writing new yaml doc into the config file") yaml.dump(yamldoc, stream) except yaml.YAMLError as exc: logging.exception("Exception occured while trying to write Yaml file") def get_file(filename): logging.debug(f'Trying to retrieve contents of file {filename}') - test_file_exists(filename) + if not test_file_exists(filename): + logging.error("Cannot work with an empty file!, please check the path of your config file.") + exit(10) with open(filename, 'r') as stream: try: config_file = yaml.safe_load(stream) @@ -52,9 +56,9 @@ def test_file_exists(filename): if exists: logging.debug("File exists!") else: - logging.error('Config File Not found!') + logging.info('Config File Not found!') # Keep presets - exit(10) + return exists def remove_resource(config_file, removing_type): logging.debug(f"Started removal of {removing_type}") @@ -87,9 +91,6 @@ def remove_resource(config_file, removing_type): return config_file -def write_file(filename, yamldoc): - logging.info("Not Implemented Yet") - @click.command() @click.argument( "resource", @@ -133,22 +134,23 @@ def cli(resource, name, kubeconfig, undo, debug): if undo: logging.info(f"Undo flag was set! checking for the backup file...") - print(f'Searching for backup config file {kubeconfig_backup}') - config_file = get_file(kubeconfig_backup) + logging.info(f'Searching for backup config file {kubeconfig_backup}') + config_file_after = get_file(kubeconfig_backup) else: - config_file = get_file(kubeconfig) + config_file_before = get_file(kubeconfig) + logging.info(f'Using resource {resource}') + logging.debug(f'Config file to use: {kubeconfig}') + if name == None: + logging.info(f'Name is empty, using fzf to search for the resource to remove') + else: + logging.info(f'Name of the resource requested to remove: {name}') + config_file_after = remove_resource(config_file_before, resource) logging.info(f'Backing up config file at {kubeconfig_backup} before doing anything') - update_file(kubeconfig_backup, config_file) - config_file = remove_resource(config_file, resource) + update_file(kubeconfig_backup, config_file_before) - logging.info(f'Using resource {resource}') - logging.debug(f'Config file to use: {kubeconfig}') - if name == None: - logging.info(f'Name is empty, using fzf to search for the resource to remove') - else: - logging.info(f'Name of the resource requested to remove: {name}') - update_file(kubeconfig, config_file) + logging.debug(f"New Config file content: \n{config_file_after}") + update_file(kubeconfig, config_file_after) if __name__ == '__main__': cli(obj={}) From 876950791f042705666903e777d5eb440666e29d Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Tue, 28 May 2019 18:20:37 -0400 Subject: [PATCH 09/27] Ignoring sample backup --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5c353f4..66a1c55 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ tests/__pycache__ coverage.xml htmlcov demo.yml +tests/sampleConfig.bak From ee18f1a3c845b0794a55c8384390edea4dc985d0 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Tue, 28 May 2019 18:40:06 -0400 Subject: [PATCH 10/27] A bit more generic --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 66a1c55..5faef56 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,4 @@ tests/__pycache__ coverage.xml htmlcov demo.yml -tests/sampleConfig.bak +tests/*.bak From 98284136b25a9a3e5a66b3beed5f7c7c9b3d3a46 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Tue, 28 May 2019 19:09:30 -0400 Subject: [PATCH 11/27] Writting a new way of backing up the versions --- kcleaner.py | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/kcleaner.py b/kcleaner.py index cf3e6ec..9a4dea0 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -5,6 +5,9 @@ import yaml from pathlib import Path from iterfzf import iterfzf +import datetime + +backup_limit = 10 def ask_yn(yn_question, default='n'): tries = 0 @@ -18,10 +21,32 @@ def ask_yn(yn_question, default='n'): break return response +def check_and_cleanup_backups(filename): + logging.debug(f"Checking if there's not more than {backup_limit} backup files in this directory") + dirpath = os.path.dirname(os.path.abspath(filename)) + logging.debug(f"Getting all the files in {dirpath}") + files = os.listdir(dirpath) + logging.debug(f"These are all the files in the directory:\n{files}") + logging.debug(f"Checking for all kcleaner backup files") + files = [item for item in files if "kcleaner.bak" in item] + logging.debug(f"These are the backup files in this folder:\n{files}") + if len(files) > 10: + logging.info(f"Cleaning up excess of backup files - we have {len(files)} already... - Removing the {len(files) - 10} oldest files") + files.sort() + for file in files[0:(len(files)-10)]: + logging.debug(f"Removing File {file}") + os.remove(f"{dirpath}/{file}") + + + + + def update_file(filename, yamldoc): test_file_exists(filename) if not test_file_exists(filename) and not "bak" in filename: logging.error("Cannot work with an empty file!, please check the path of your config file.") + if "bak" in filename: + check_and_cleanup_backups(filename) logging.debug(f"Opening write stream for file {filename}") with open(filename, 'w') as stream: try: @@ -130,7 +155,8 @@ def cli(resource, name, kubeconfig, undo, debug): else: logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s') - kubeconfig_backup = f"{kubeconfig}.bak" + kubeconfig_dir = os.path.dirname(os.path.abspath(kubeconfig)) + kubeconfig_backup = f"{kubeconfig_dir}/{datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}_kcleaner.bak" if undo: logging.info(f"Undo flag was set! checking for the backup file...") @@ -138,6 +164,7 @@ def cli(resource, name, kubeconfig, undo, debug): config_file_after = get_file(kubeconfig_backup) else: config_file_before = get_file(kubeconfig) + update_file(kubeconfig_backup, config_file_before) logging.info(f'Using resource {resource}') logging.debug(f'Config file to use: {kubeconfig}') if name == None: @@ -146,7 +173,6 @@ def cli(resource, name, kubeconfig, undo, debug): logging.info(f'Name of the resource requested to remove: {name}') config_file_after = remove_resource(config_file_before, resource) logging.info(f'Backing up config file at {kubeconfig_backup} before doing anything') - update_file(kubeconfig_backup, config_file_before) logging.debug(f"New Config file content: \n{config_file_after}") From 08aaade04e731615a38da04589b5828bc6d20ad1 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Tue, 28 May 2019 19:14:39 -0400 Subject: [PATCH 12/27] Just so GIT stops complaining --- tests/sampleConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sampleConfig b/tests/sampleConfig index 90be8d9..f6a9132 100644 --- a/tests/sampleConfig +++ b/tests/sampleConfig @@ -120,4 +120,4 @@ users: apiserver-id: some-id-that-makes-sense client-id: some-id-that-makes-sense tenant-id: some-id-that-makes-sense - name: some-auth-provider \ No newline at end of file + name: some-auth-provider From 3f2081a7770f02b76e1407c2555c2cc01c2ffee1 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Tue, 28 May 2019 19:15:03 -0400 Subject: [PATCH 13/27] Working Backup feature :) --- kcleaner.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/kcleaner.py b/kcleaner.py index 9a4dea0..9c4183e 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -37,10 +37,6 @@ def check_and_cleanup_backups(filename): logging.debug(f"Removing File {file}") os.remove(f"{dirpath}/{file}") - - - - def update_file(filename, yamldoc): test_file_exists(filename) if not test_file_exists(filename) and not "bak" in filename: @@ -85,6 +81,17 @@ def test_file_exists(filename): # Keep presets return exists +def get_backup(backup_path): + logging.debug(f"Checking all backups available in the directory {backup_path}") + files = os.listdir(backup_path) + logging.debug(f"These are all the files in the directory:\n{files}") + logging.debug(f"Checking for all kcleaner backup files") + files = [item for item in files if "kcleaner.bak" in item] + logging.debug(f"These are the backup files in this folder:\n{files}") + backup_to_use = iterfzf(files) + return get_file(f"{backup_path}/{backup_to_use}") + + def remove_resource(config_file, removing_type): logging.debug(f"Started removal of {removing_type}") resources_name_list = [] @@ -161,7 +168,7 @@ def cli(resource, name, kubeconfig, undo, debug): if undo: logging.info(f"Undo flag was set! checking for the backup file...") logging.info(f'Searching for backup config file {kubeconfig_backup}') - config_file_after = get_file(kubeconfig_backup) + config_file_after = get_backup(kubeconfig_dir) else: config_file_before = get_file(kubeconfig) update_file(kubeconfig_backup, config_file_before) From abe17e72eae43d4e03c4a2d185f4956aebe785b1 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Tue, 28 May 2019 19:16:39 -0400 Subject: [PATCH 14/27] Some sorting.. We're not animals --- kcleaner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/kcleaner.py b/kcleaner.py index 9c4183e..52165a4 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -88,6 +88,7 @@ def get_backup(backup_path): logging.debug(f"Checking for all kcleaner backup files") files = [item for item in files if "kcleaner.bak" in item] logging.debug(f"These are the backup files in this folder:\n{files}") + files.sort() backup_to_use = iterfzf(files) return get_file(f"{backup_path}/{backup_to_use}") From 035c3d7f68e9090d5ce40b9ee046b79122fdd604 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Wed, 29 May 2019 09:58:33 -0400 Subject: [PATCH 15/27] Using reverse order for backups --- kcleaner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kcleaner.py b/kcleaner.py index 52165a4..87b1911 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -88,7 +88,7 @@ def get_backup(backup_path): logging.debug(f"Checking for all kcleaner backup files") files = [item for item in files if "kcleaner.bak" in item] logging.debug(f"These are the backup files in this folder:\n{files}") - files.sort() + files.sort(reverse=True) backup_to_use = iterfzf(files) return get_file(f"{backup_path}/{backup_to_use}") From 473486761706edaa0780c31bbdd515b4f4ad7c57 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Wed, 29 May 2019 11:38:16 -0400 Subject: [PATCH 16/27] Outputing dates Properly --- kcleaner.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kcleaner.py b/kcleaner.py index 87b1911..6780cec 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -89,7 +89,11 @@ def get_backup(backup_path): files = [item for item in files if "kcleaner.bak" in item] logging.debug(f"These are the backup files in this folder:\n{files}") files.sort(reverse=True) - backup_to_use = iterfzf(files) + dates = [] + for file in files: + dates.append((datetime.datetime.strptime("_".join(file.split('_')[0:2]), '%Y-%m-%d_%H-%M-%S').strftime("%c"))) + logging.debug(dates) + backup_to_use = iterfzf(dates) return get_file(f"{backup_path}/{backup_to_use}") From 2c86210f7f5fbd497082ba5695e113ec9e4f5f5d Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Wed, 29 May 2019 11:48:54 -0400 Subject: [PATCH 17/27] Better format to search logs --- kcleaner.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kcleaner.py b/kcleaner.py index 6780cec..47039fe 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -8,6 +8,7 @@ import datetime backup_limit = 10 +backup_date_format = '%Y-%m-%d_%H-%M-%S' def ask_yn(yn_question, default='n'): tries = 0 @@ -91,10 +92,13 @@ def get_backup(backup_path): files.sort(reverse=True) dates = [] for file in files: - dates.append((datetime.datetime.strptime("_".join(file.split('_')[0:2]), '%Y-%m-%d_%H-%M-%S').strftime("%c"))) + dates.append((datetime.datetime.strptime("_".join(file.split('_')[0:2]), backup_date_format).strftime("%c"))) logging.debug(dates) backup_to_use = iterfzf(dates) - return get_file(f"{backup_path}/{backup_to_use}") + logging.debug(f'Backup chosen: {backup_to_use}') + backup_file_to_use = f"{datetime.datetime.strptime(backup_to_use, '%c').strftime(backup_date_format)}_kcleaner.bak" + logging.debug(f'Backup file: {backup_file_to_use}') + return get_file(f"{backup_path}/{backup_file_to_use}") def remove_resource(config_file, removing_type): @@ -168,7 +172,7 @@ def cli(resource, name, kubeconfig, undo, debug): logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s') kubeconfig_dir = os.path.dirname(os.path.abspath(kubeconfig)) - kubeconfig_backup = f"{kubeconfig_dir}/{datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}_kcleaner.bak" + kubeconfig_backup = f"{kubeconfig_dir}/{datetime.datetime.now().strftime(backup_date_format)}_kcleaner.bak" if undo: logging.info(f"Undo flag was set! checking for the backup file...") From ce99b7507a0cdb996af09bf9e2e5b04880a1eeff Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Wed, 29 May 2019 12:23:31 -0400 Subject: [PATCH 18/27] Logging cleanup --- kcleaner.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kcleaner.py b/kcleaner.py index 47039fe..aa9437f 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -176,19 +176,19 @@ def cli(resource, name, kubeconfig, undo, debug): if undo: logging.info(f"Undo flag was set! checking for the backup file...") - logging.info(f'Searching for backup config file {kubeconfig_backup}') + logging.debug(f'Searching for backup config file {kubeconfig_backup}') config_file_after = get_backup(kubeconfig_dir) else: config_file_before = get_file(kubeconfig) + logging.debug(f'Backing up config file at {kubeconfig_backup} before doing anything') update_file(kubeconfig_backup, config_file_before) logging.info(f'Using resource {resource}') logging.debug(f'Config file to use: {kubeconfig}') if name == None: - logging.info(f'Name is empty, using fzf to search for the resource to remove') + logging.debug(f'Name is empty, using fzf to search for the resource to remove') else: - logging.info(f'Name of the resource requested to remove: {name}') + logging.debug(f'Name of the resource requested to remove: {name}') config_file_after = remove_resource(config_file_before, resource) - logging.info(f'Backing up config file at {kubeconfig_backup} before doing anything') logging.debug(f"New Config file content: \n{config_file_after}") From 75232bc2787b80fe7151d470ce9e7358946c12c6 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Wed, 29 May 2019 12:49:12 -0400 Subject: [PATCH 19/27] Fixed tests --- tests/kcleaner_config_file_test.py | 34 ++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/tests/kcleaner_config_file_test.py b/tests/kcleaner_config_file_test.py index 17b57da..65af322 100644 --- a/tests/kcleaner_config_file_test.py +++ b/tests/kcleaner_config_file_test.py @@ -1,29 +1,49 @@ import click from click.testing import CliRunner from kcleaner import cli +from testfixtures import log_capture + runner = CliRunner() -def test_clean_non_existant_file(): + +@log_capture() +def test_clean_non_existant_file(capture): results = runner.invoke(cli, ['-k', './non_existent_file']) - assert results.exit_code == 10 - assert 'Config File Not found!' in results.output + capture.check_present( + ('root', 'DEBUG', 'Trying to retrieve contents of file ./non_existent_file'), + ('root', 'DEBUG', 'checking if file ./non_existent_file exists...'), + ('root', 'INFO', 'Config File Not found!'), + ('root', 'ERROR', 'Cannot work with an empty file!, please check the path of your config file.'), + ) -def test_clean_empty_file(): +@log_capture() +def test_clean_empty_file(capture): with runner.isolated_filesystem(): with open('./config', 'w') as f: f.write('') result = runner.invoke(cli, ['-k', './config']) assert result.exit_code == 11 - assert "Config File is empty! Can't use it." in result.output + capture.check_present( + ('root', 'DEBUG', 'Trying to retrieve contents of file ./config'), + ('root', 'DEBUG', 'checking if file ./config exists...'), + ('root', 'DEBUG', 'File exists!'), + ('root', 'DEBUG', "Type of the file contents: "), + ('root', 'ERROR', "Config File is empty! Can't use it.") + ) -def test_non_valid_yaml(): +@log_capture() +def test_non_valid_yaml(capture): with runner.isolated_filesystem(): with open('./config', 'w') as f: f.write('lololol') result = runner.invoke(cli, ['-k', './config']) assert result.exit_code == 12 - assert "Config File is not a valid yaml file!" in result.output \ No newline at end of file + capture.check_present( + ('root', 'DEBUG', 'checking if file ./config exists...'), + ('root', 'DEBUG', 'File exists!'), + ('root', 'ERROR', 'Config File is not a valid yaml file!'), + ) \ No newline at end of file From a4553f50bf4fd3b96561f6668629382797c55c14 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Wed, 29 May 2019 13:02:15 -0400 Subject: [PATCH 20/27] Adding new dependency for testing logs --- azure-pipelines.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 0709d39..60424a3 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -50,6 +50,7 @@ steps: python -m pip install --upgrade pip pip install pytest-cov pip install . + pip install testfixtures displayName: 'Install dependencies' - script: | From bcbb27deffdc1f68a1c45e7f547fab0586427fd1 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Wed, 29 May 2019 14:58:59 -0400 Subject: [PATCH 21/27] Added missing conditions --- kcleaner.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/kcleaner.py b/kcleaner.py index aa9437f..171faa9 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -39,8 +39,8 @@ def check_and_cleanup_backups(filename): os.remove(f"{dirpath}/{file}") def update_file(filename, yamldoc): - test_file_exists(filename) - if not test_file_exists(filename) and not "bak" in filename: + file_exists(filename) + if not file_exists(filename) and not "bak" in filename: logging.error("Cannot work with an empty file!, please check the path of your config file.") if "bak" in filename: check_and_cleanup_backups(filename) @@ -54,7 +54,7 @@ def update_file(filename, yamldoc): def get_file(filename): logging.debug(f'Trying to retrieve contents of file {filename}') - if not test_file_exists(filename): + if not file_exists(filename): logging.error("Cannot work with an empty file!, please check the path of your config file.") exit(10) with open(filename, 'r') as stream: @@ -72,8 +72,14 @@ def get_file(filename): exit(12) return config_file -def test_file_exists(filename): +def file_exists(filename): logging.debug(f"checking if file {filename} exists...") + if filename == None: + logging.error("Filename cannot be 'None'") + exit(20) + elif filename == "": + logging.error("Filename cannot be empty!") + exit(21) exists = os.path.isfile(filename) if exists: logging.debug("File exists!") From 361a01983845d3d9f62b9b9aee8c0aca8c604e58 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Wed, 29 May 2019 14:59:18 -0400 Subject: [PATCH 22/27] Added tests for file_exists function --- tests/kcleaner_test_file_exists_test.py | 54 +++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tests/kcleaner_test_file_exists_test.py diff --git a/tests/kcleaner_test_file_exists_test.py b/tests/kcleaner_test_file_exists_test.py new file mode 100644 index 0000000..9f9f06a --- /dev/null +++ b/tests/kcleaner_test_file_exists_test.py @@ -0,0 +1,54 @@ +from kcleaner import file_exists +from testfixtures import log_capture +import click +from click.testing import CliRunner +import pytest + +runner = CliRunner() + +@log_capture() +def test_no_parameters(capture): + + with pytest.raises(SystemExit) as pytest_wrapped_e: + file_exists(None) + + assert pytest_wrapped_e.value.code == 20 + capture.check_present( + ('root', 'ERROR', "Filename cannot be 'None'") + ) + +@log_capture() +def test_empty_string(capture): + + with pytest.raises(SystemExit) as pytest_wrapped_e: + file_exists("") + + assert pytest_wrapped_e.value.code == 21 + capture.check_present( + ('root', 'ERROR', "Filename cannot be empty!") + ) + +@log_capture() +def test_existing_file(capture): + with runner.isolated_filesystem(): + with open('./config', 'w') as f: + f.write('lololol') + + exists = file_exists("./config") + + assert exists == True + capture.check_present( + ('root', 'DEBUG', 'File exists!') + ) + +@log_capture() +def test_non_existing_file(capture): + with runner.isolated_filesystem(): + + exists = file_exists("./config") + + assert exists == False + capture.check_present( + ('root', 'INFO', 'Config File Not found!') + ) + From e9ef98dd5ac04752c892bd694771f96a7dfe2dd4 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Wed, 29 May 2019 16:57:37 -0400 Subject: [PATCH 23/27] Passing some tests --- kcleaner.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/kcleaner.py b/kcleaner.py index 171faa9..204dc18 100755 --- a/kcleaner.py +++ b/kcleaner.py @@ -44,6 +44,17 @@ def update_file(filename, yamldoc): logging.error("Cannot work with an empty file!, please check the path of your config file.") if "bak" in filename: check_and_cleanup_backups(filename) + if yamldoc == None: + logging.error("Yaml Value cannot be 'None'!") + exit(30) + elif yamldoc == "": + logging.error("Yaml Value cannot be empty!") + exit(31) + try: + yaml.safe_load(yamldoc) + except: + logging.exception("Yaml value is not valid!") + exit(32) logging.debug(f"Opening write stream for file {filename}") with open(filename, 'w') as stream: try: @@ -85,7 +96,6 @@ def file_exists(filename): logging.debug("File exists!") else: logging.info('Config File Not found!') - # Keep presets return exists def get_backup(backup_path): From 1fb5165291221a1516a775d8c2cdbdd2279b0574 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Wed, 29 May 2019 16:57:52 -0400 Subject: [PATCH 24/27] Renamed the tests of the cli itself --- tests/{kcleaner_config_file_test.py => kcleaner_test.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{kcleaner_config_file_test.py => kcleaner_test.py} (100%) diff --git a/tests/kcleaner_config_file_test.py b/tests/kcleaner_test.py similarity index 100% rename from tests/kcleaner_config_file_test.py rename to tests/kcleaner_test.py From 632558a251748a1a30edb84fe5ead78904e52371 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Wed, 29 May 2019 16:58:06 -0400 Subject: [PATCH 25/27] Renamed tests for file_exists --- ...aner_test_file_exists_test.py => kcleaner_file_exists_test.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{kcleaner_test_file_exists_test.py => kcleaner_file_exists_test.py} (100%) diff --git a/tests/kcleaner_test_file_exists_test.py b/tests/kcleaner_file_exists_test.py similarity index 100% rename from tests/kcleaner_test_file_exists_test.py rename to tests/kcleaner_file_exists_test.py From 399968fe47efbf1e23bbd5f028b5bc3320ff6ab7 Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Wed, 29 May 2019 16:58:15 -0400 Subject: [PATCH 26/27] Added tests for update_file --- tests/kcleaner_update_file_test.py | 97 ++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 tests/kcleaner_update_file_test.py diff --git a/tests/kcleaner_update_file_test.py b/tests/kcleaner_update_file_test.py new file mode 100644 index 0000000..696ecf6 --- /dev/null +++ b/tests/kcleaner_update_file_test.py @@ -0,0 +1,97 @@ +from kcleaner import update_file +from testfixtures import log_capture +import click +from click.testing import CliRunner +import pytest +import yaml + +runner = CliRunner() +sample_yaml = """ +something: + alist: + - item1: test + something: test + - item2: test + something: test +""" + +@log_capture() +def test_none_parameters(capture): + + with pytest.raises(SystemExit) as pytest_wrapped_e: + update_file(None, None) + + assert pytest_wrapped_e.value.code == 20 + capture.check_present( + ('root', 'ERROR', "Filename cannot be 'None'") + ) + +@log_capture() +def test_none_file_empty_content(capture): + + with pytest.raises(SystemExit) as pytest_wrapped_e: + update_file(None, "") + + assert pytest_wrapped_e.value.code == 20 + capture.check_present( + ('root', 'ERROR', "Filename cannot be 'None'") + ) + +@log_capture() +def test_empty_file_empty_content(capture): + + with pytest.raises(SystemExit) as pytest_wrapped_e: + update_file("", "") + + assert pytest_wrapped_e.value.code == 21 + capture.check_present( + ('root', 'ERROR', 'Filename cannot be empty!') + ) + +@log_capture() +def test_non_existant_file_none_content(capture): + with runner.isolated_filesystem(): + with pytest.raises(SystemExit) as pytest_wrapped_e: + update_file("./config", None) + + assert pytest_wrapped_e.value.code == 30 + capture.check_present( + ('root', 'ERROR', "Yaml Value cannot be 'None'!") + ) + +@log_capture() +def test_non_existant_file_empty_content(capture): + with runner.isolated_filesystem(): + with pytest.raises(SystemExit) as pytest_wrapped_e: + update_file("./config", "") + + assert pytest_wrapped_e.value.code == 31 + capture.check_present( + ('root', 'ERROR', 'Yaml Value cannot be empty!') + ) + +@log_capture() +def test_non_existant_file_not_yaml_content(capture): + with runner.isolated_filesystem(): + with pytest.raises(SystemExit) as pytest_wrapped_e: + update_file("./config", "{{123lololol123}}") + + assert pytest_wrapped_e.value.code == 32 + capture.check_present( + ('root', 'ERROR', 'Yaml value is not valid!') + ) + +@log_capture() +def test_existant_file_yaml_content(capture): + with runner.isolated_filesystem(): + with open('./config', 'w') as f: + f.write('lololol') + update_file("./config", sample_yaml) + + with open('./config', 'r') as f: + result = yaml.safe_load(f) + + assert sample_yaml in result + capture.check_present( + ('root', 'DEBUG', 'Writing new yaml doc into the config file') + ) \ No newline at end of file From 630c7676dad283311693941dbfae0f13ccd4df9c Mon Sep 17 00:00:00 2001 From: Guilherme Carraro Martins Date: Wed, 29 May 2019 17:01:00 -0400 Subject: [PATCH 27/27] Bumping up the version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0a9732b..653a9d3 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name='kcleaner', - version='0.1.2', + version='0.2.0', author='Gui Martins', url='https://fancywhale.ca/', author_email='gui.martins.94@outlook.com',