From 9b9424594ac7545d8e9ad7deb3d186fb44f716bb Mon Sep 17 00:00:00 2001 From: ggatward Date: Tue, 3 Jan 2017 20:01:03 +1100 Subject: [PATCH] Publish/Promote datestamps --- README.md | 12 +++++++++++ promote_content_views.py | 45 +++++++++++++++++++++++++++++++++++++--- publish_content_views.py | 43 +++++++++++++++++++++++++++++++++++--- sat_import.py | 19 ++++++++++++++--- 4 files changed, 110 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index e5e1fab..0440904 100644 --- a/README.md +++ b/README.md @@ -351,6 +351,11 @@ Publishes new content to the Library environment. The following can be published The dry run (-d) option can be used to see what would be published for a given command input. +Each time a content view is published or promoted, a datestamp is recorded so that +the last publish/promote date can be viewed with the (-l) option. Note that this +datestamp is only updated by this script - it does NOT record publish/promote via +the WebUI or Hammer CLI. + The defaults are configured in the main config.yml file in a YAML block like this: ``` publish: @@ -371,6 +376,7 @@ optional arguments: -o ORG, --org ORG Organization (Uses default if not specified) -a, --all Publish ALL content views -d, --dryrun Dry Run - Only show what will be published + -l, --last Display last promotions ``` ### Examples @@ -394,6 +400,11 @@ The following can be promoted: The dry run (-d) option can be used to see what would be promoted for a given command input. +Each time a content view is published or promoted, a datestamp is recorded so that +the last publish/promote date can be viewed with the (-l) option. Note that this +datestamp is only updated by this script - it does NOT record publish/promote via +the WebUI or Hammer CLI. + The defaults are configured in the main config.yml file in a YAML block like this: ``` promotion: @@ -425,6 +436,7 @@ optional arguments: -o ORG, --org ORG Organization (Uses default if not specified) -a, --all Promote ALL content views -d, --dryrun Dry Run - Only show what will be promoted + -l, --last Display last promotions ``` ### Examples diff --git a/promote_content_views.py b/promote_content_views.py index 6ed79ec..58bc428 100755 --- a/promote_content_views.py +++ b/promote_content_views.py @@ -12,7 +12,11 @@ """ #pylint: disable-msg=R0912,R0913,R0914,R0915 -import sys, argparse +import sys +import os +import argparse +import datetime +import pickle import simplejson as json import helpers @@ -174,19 +178,28 @@ def main(args): # Who is running this script? runuser = helpers.who_is_running() + # Set the base dir of the script and where the var data is + global dir + global vardir + dir = os.path.dirname(__file__) + vardir = os.path.join(dir, 'var') +# confdir = os.path.join(dir, 'config') + # Check for sane input parser = argparse.ArgumentParser( description='Promotes content views for specified organization to the target environment.') group = parser.add_mutually_exclusive_group() # pylint: disable=bad-continuation parser.add_argument('-e', '--env', help='Target Environment (e.g. Development, Quality, Production)', - required=True) + required=False) parser.add_argument('-o', '--org', help='Organization (Uses default if not specified)', required=False) group.add_argument('-a', '--all', help='Promote ALL content views', required=False, action="store_true") parser.add_argument('-d', '--dryrun', help='Dry Run - Only show what will be promoted', required=False, action="store_true") + parser.add_argument('-l', '--last', help='Display last promotions', required=False, + action="store_true") args = parser.parse_args() @@ -202,6 +215,28 @@ def main(args): target_env = args.env dry_run = args.dryrun + # Load the promotion history + if not os.path.exists(vardir + '/promotions.pkl'): + if not os.path.exists(vardir): + os.makedirs(vardir) + phistory = {} + else: + phistory = pickle.load(open(vardir + '/promotions.pkl', 'rb')) + + # Read the promotion history if --last requested + if args.last: + if phistory: + print 'Last promotions:' + for lenv, time in phistory.iteritems(): + print lenv, time + else: + print 'No promotions recorded' + sys.exit(-1) + + # Error if no environment to promote to is given + if args.env is None: + parser.error('--env is required') + promote_list = [] if not args.all: for x in helpers.CONFIG['promotion']: @@ -209,7 +244,7 @@ def main(args): promote_list = helpers.CONFIG['promotion'][x]['content_views'] if not promote_list: - msg = "Cannot find promotion configuration for '" + target_env + msg = "Cannot find promotion configuration for '" + target_env + "'" helpers.log_msg(msg, 'ERROR') sys.exit(-1) @@ -230,6 +265,10 @@ def main(args): (task_list, ref_list, task_name) = promote(target_env, ver_list, ver_descr, ver_version, env_list, prior_list, dry_run) + # Add/Update the promotion history dictionary so we can check when we last promoted + phistory[target_env] = datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d') + pickle.dump(phistory, open(vardir + '/promotions.pkl', 'wb')) + # Monitor the status of the promotion tasks helpers.watch_tasks(task_list, ref_list, task_name) diff --git a/publish_content_views.py b/publish_content_views.py index b12946b..bfff171 100755 --- a/publish_content_views.py +++ b/publish_content_views.py @@ -12,7 +12,11 @@ """ #pylint: disable-msg=R0912,R0913,R0914,R0915 -import sys, argparse +import sys +import os +import argparse +import datetime +import pickle import simplejson as json import helpers @@ -112,6 +116,13 @@ def main(args): # Who is running this script? runuser = helpers.who_is_running() + # Set the base dir of the script and where the var data is + global dir + global vardir + dir = os.path.dirname(__file__) + vardir = os.path.join(dir, 'var') + confdir = os.path.join(dir, 'config') + # Check for sane input parser = argparse.ArgumentParser( description='Publishes content views for specified organization.') @@ -123,12 +134,15 @@ def main(args): action="store_true") parser.add_argument('-d', '--dryrun', help='Dry Run - Only show what will be published', required=False, action="store_true") + parser.add_argument('-l', '--last', help='Display last promotions', required=False, + action="store_true") args = parser.parse_args() # Log the fact we are starting - msg = "-------- Content view publish started by " + runuser + " -----------" - helpers.log_msg(msg, 'INFO') + if not args.last: + msg = "-------- Content view publish started by " + runuser + " -----------" + helpers.log_msg(msg, 'INFO') # Set our script variables from the input args if args.org: @@ -137,6 +151,25 @@ def main(args): org_name = helpers.ORG_NAME dry_run = args.dryrun + # Load the promotion history + if not os.path.exists(vardir + '/promotions.pkl'): + if not os.path.exists(vardir): + os.makedirs(vardir) + phistory = {} + else: + phistory = pickle.load(open(vardir + '/promotions.pkl', 'rb')) + + # Read the promotion history if --last requested + if args.last: + if phistory: + print 'Last promotions:' + for lenv, time in phistory.iteritems(): + print lenv, time + else: + print 'No promotions recorded' + sys.exit(-1) + + publish_list = [] if not args.all: publish_list = helpers.CONFIG['publish']['content_views'] @@ -158,6 +191,10 @@ def main(args): # Publish the content views. Returns a list of task IDs. (task_list, ref_list, task_name) = publish(ver_list, ver_descr, ver_version, dry_run, runuser) + # Add/Update the promotion history dictionary so we can check when we last promoted + phistory['Library'] = datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d') + pickle.dump(phistory, open(vardir + '/promotions.pkl', 'wb')) + # Monitor the status of the publish tasks helpers.watch_tasks(task_list, ref_list, task_name) diff --git a/sat_import.py b/sat_import.py index 9ff774f..a7e2eaa 100755 --- a/sat_import.py +++ b/sat_import.py @@ -173,7 +173,7 @@ def count_packages(repo_id): return numpkg, numerrata -def check_counts(org_id, package_count): +def check_counts(org_id, package_count, count): """ Verify the number of pkgs/errutum in each repo match the sync host. Input is a dictionary loaded from a pickle that was created on the sync @@ -205,19 +205,30 @@ def check_counts(org_id, package_count): # Set the output colour of the table entry based on the pkg counts if int(local_pkgs) == int(sync_pkgs): colour = helpers.GREEN + display = False elif int(local_pkgs) == 0 and int(sync_pkgs) != 0: colour = helpers.RED + display = True elif int(local_pkgs) < int(sync_pkgs): colour = helpers.YELLOW + display = True else: # If local_pkg > sync_pkg - can happen due to 'mirror on sync' option # - sync host deletes old pkgs. If this is the case we cannot verify # an exact package status so we'll set BLUE colour = helpers.BLUE + display = True # Tuncate the repo label to 70 chars and build the table row reponame = "{:<70}".format(repo) - table_data.append([colour, repo[:70], str(sync_pkgs), str(local_pkgs), helpers.ENDC]) + # Add all counts if it has been requested + if count: + table_data.append([colour, repo[:70], str(sync_pkgs), str(local_pkgs), helpers.ENDC]) + else: + # Otherwise only add counts that are non-green (display = True) + if display: + table_data.append([colour, repo[:70], str(sync_pkgs), str(local_pkgs), helpers.ENDC]) + msg = '\nRepository package count verification...' helpers.log_msg(msg, 'INFO') @@ -273,6 +284,8 @@ def main(args): required=False, action="store_true") parser.add_argument('-l', '--last', help='Display the last successful import performed', required=False, action="store_true") + parser.add_argument('-c', '--count', help='Display all package counts after import', + required=False, action="store_true") args = parser.parse_args() # Set our script variables from the input args @@ -335,7 +348,7 @@ def main(args): print 'Please publish content views to make new content available.' # Verify the repository package/erratum counts match the sync host - check_counts(org_id, package_count) + check_counts(org_id, package_count, args.count) if os.path.exists(helpers.IMPORTDIR + '/puppetforge'): print 'Offline puppet-forge-server bundle is available to import seperately in '\