def main(): args = parse_args() system_paasta_config = load_system_paasta_config() cluster = system_paasta_config.get_cluster() service, instance = chronos_tools.decompose_job_id(args.service_instance) config = chronos_tools.load_chronos_config() client = chronos_tools.get_chronos_client(config) related_jobs = chronos_tools.get_related_jobs_configs(cluster, service, instance, soa_dir=args.soa_dir) if not related_jobs: error_msg = "No deployment found for {} in cluster {}. Has Jenkins run for it?".format( args.service_instance, cluster, ) paasta_print(error_msg) raise NoDeploymentsAvailable if not args.run_all_related_jobs: # Strip all the configuration for the related services # those information will not be used by the rest of the flow related_jobs = { (service, instance): related_jobs[(service, instance)], } complete_job_configs = {} for (srv, inst) in related_jobs: try: complete_job_configs.update( { (srv, inst): chronos_tools.create_complete_config( service=srv, job_name=inst, soa_dir=args.soa_dir, ), }, ) except (NoDeploymentsAvailable, NoDockerImageError) as e: error_msg = "No deployment found for {} in cluster {}. Has Jenkins run for it?".format( chronos_tools.compose_job_id(srv, inst), cluster, ) paasta_print(error_msg) raise e except NoConfigurationForServiceError as e: error_msg = ( "Could not read chronos configuration file for {} in cluster {}\nError was: {}" .format( chronos_tools.compose_job_id(srv, inst), cluster, str(e), )) paasta_print(error_msg) raise e except chronos_tools.InvalidParentError as e: raise e if not args.run_all_related_jobs: sorted_jobs = [(service, instance)] else: sorted_jobs = chronos_tools.topological_sort_related_jobs( cluster, service, instance, soa_dir=args.soa_dir) timestamp = datetime.datetime.utcnow().isoformat() chronos_to_add = [] for (service, instance) in sorted_jobs: # complete_job_config is a formatted version of the job, # so the command is formatted in the context of 'now' # replace it with the 'original' cmd so it can be re rendered chronos_job_config = chronos_tools.load_chronos_job_config( service=service, instance=instance, cluster=cluster, soa_dir=args.soa_dir, ) original_command = chronos_job_config.get_cmd() complete_job_config = complete_job_configs[(service, instance)] complete_job_config['command'] = original_command clone = clone_job( chronos_job=complete_job_config, timestamp=timestamp, force_disabled=args.force_disabled, ) # modify the command to run commands for a given date clone = modify_command_for_date( chronos_job=clone, date=datetime.datetime.strptime(args.execution_date, "%Y-%m-%dT%H:%M:%S"), verbose=args.verbose, ) if not args.run_all_related_jobs and chronos_tools.get_job_type( clone) == chronos_tools.JobType.Dependent: # If the job is a dependent job and we want to re-run only the specific instance # remove the parents and update the schedule to start the job as soon as possible clone = set_default_schedule(remove_parents(clone)) chronos_to_add.append(clone) for job_to_add in chronos_to_add: client.add(job_to_add)
def paasta_rerun(args): """Reruns a Chronos job. :param args: argparse.Namespace obj created from sys.args by cli""" system_paasta_config = load_system_paasta_config() soa_dir = args.soa_dir service = figure_out_service_name( args, soa_dir) # exit with an error if the service doesn't exist if args.execution_date: execution_date = args.execution_date else: execution_date = None all_clusters = list_clusters(soa_dir=soa_dir) actual_deployments = get_actual_deployments( service, soa_dir) # cluster.instance: sha if actual_deployments: deploy_pipeline = list(get_planned_deployments( service, soa_dir)) # cluster.instance deployed_clusters = list_deployed_clusters(deploy_pipeline, actual_deployments) deployed_cluster_instance = _get_cluster_instance( actual_deployments.keys()) if args.clusters is not None: clusters = args.clusters.split(",") else: clusters = deployed_clusters for cluster in clusters: paasta_print("cluster: %s" % cluster) if cluster not in all_clusters: paasta_print( " Warning: \"%s\" does not look like a valid cluster." % cluster) continue if cluster not in deployed_clusters: paasta_print( f" Warning: service \"{service}\" has not been deployed to \"{cluster}\" yet." ) continue if not deployed_cluster_instance[cluster].get(args.instance, False): paasta_print((" Warning: instance \"%s\" is either invalid " "or has not been deployed to \"%s\" yet." % (args.instance, cluster))) continue try: chronos_job_config = chronos_tools.load_chronos_job_config( service, args.instance, cluster, load_deployments=False, soa_dir=soa_dir, ) if chronos_tools.uses_time_variables( chronos_job_config) and execution_date is None: paasta_print( (" Warning: \"%s\" uses time variables interpolation, " "please supply a `--execution_date` argument." % args.instance)) continue except NoConfigurationForServiceError as e: paasta_print(" Warning: %s" % e) continue if execution_date is None: execution_date = _get_default_execution_date() related_job_configs = get_related_jobs_configs(cluster, service, args.instance) if not args.rerun_type and len(related_job_configs) > 1: instance_names = sorted([ f'- {srv}{chronos_tools.INTERNAL_SPACER}{inst}' for srv, inst in related_job_configs if srv != service or inst != args.instance ]) paasta_print(PaastaColors.red(' error')) paasta_print( 'Instance {instance} has dependency relations with the following jobs:\n' '{relations}\n' '\n' 'Please specify the rerun policy via --rerun-type argument'. format( instance=args.instance, relations='\n'.join(instance_names), ), ) return rc, output = execute_chronos_rerun_on_remote_master( service=service, instancename=args.instance, cluster=cluster, verbose=args.verbose, execution_date=execution_date.strftime( chronos_tools.EXECUTION_DATE_FORMAT), system_paasta_config=system_paasta_config, run_all_related_jobs=args.rerun_type == 'graph', force_disabled=args.force_disabled, ) if rc == 0: paasta_print(PaastaColors.green(' successfully created job')) else: paasta_print(PaastaColors.red(' error')) paasta_print(output)