def get_versions_for_service( service: str, deploy_groups: Collection[str], soa_dir: str) -> Mapping[DeploymentVersion, Tuple[str, str]]: """Returns a dictionary of 2-tuples of the form (timestamp, deploy_group) for each version tuple of (deploy sha, image_version)""" if service is None: return {} git_url = get_git_url(service=service, soa_dir=soa_dir) all_deploy_groups = list_deploy_groups(service=service, soa_dir=soa_dir) deploy_groups, _ = validate_given_deploy_groups(all_deploy_groups, deploy_groups) previously_deployed_versions: Dict[DeploymentVersion, Tuple[str, str]] = {} for ref, sha in list_remote_refs(git_url).items(): regex_match = extract_tags(ref) try: deploy_group = regex_match["deploy_group"] tstamp = regex_match["tstamp"] image_version = regex_match["image_version"] except KeyError: pass else: # Now we filter and dedup by picking the most recent sha for a deploy group # Note that all strings are greater than '' if deploy_group in deploy_groups: version = DeploymentVersion(sha=sha, image_version=image_version) tstamp_so_far = previously_deployed_versions.get( version, ("all", ""))[1] if tstamp > tstamp_so_far: previously_deployed_versions[version] = (tstamp, deploy_group) return previously_deployed_versions
def get_git_shas_for_service(service, deploy_groups, soa_dir): """Returns a dictionary of 2-tuples of the form (timestamp, deploy_group) for each deploy sha""" if service is None: return [] git_url = get_git_url(service=service, soa_dir=soa_dir) all_deploy_groups = list_deploy_groups( service=service, soa_dir=soa_dir, ) deploy_groups, _ = validate_given_deploy_groups(all_deploy_groups, deploy_groups) previously_deployed_shas = {} for ref, sha in list_remote_refs(git_url).items(): regex_match = extract_tags(ref) try: deploy_group = regex_match['deploy_group'] tstamp = regex_match['tstamp'] except KeyError: pass else: # Now we filter and dedup by picking the most recent sha for a deploy group # Note that all strings are greater than '' if deploy_group in deploy_groups: tstamp_so_far = previously_deployed_shas.get(sha, ('all', ''))[1] if tstamp > tstamp_so_far: previously_deployed_shas[sha] = (tstamp, deploy_group) return previously_deployed_shas
def paasta_rollback(args): """Call mark_for_deployment with rollback parameters :param args: contains all the arguments passed onto the script: service, deploy groups and sha. These arguments will be verified and passed onto mark_for_deployment. """ soa_dir = args.soa_dir service = figure_out_service_name(args, soa_dir) git_url = get_git_url(service, soa_dir) given_deploy_groups = {deploy_group for deploy_group in args.deploy_groups.split(",") if deploy_group} all_deploy_groups = list_deploy_groups(service=service, soa_dir=soa_dir) deploy_groups, invalid = validate_given_deploy_groups(all_deploy_groups, given_deploy_groups) if len(invalid) > 0: paasta_print( PaastaColors.yellow( "These deploy groups are not valid and will be skipped: %s.\n" % (",").join(invalid), ), ) if len(deploy_groups) == 0: paasta_print(PaastaColors.red("ERROR: No valid deploy groups specified for %s.\n" % (service))) return 1 git_shas = get_git_shas_for_service(service, deploy_groups, soa_dir) commit = args.commit if not commit: paasta_print("Please specify a commit to mark for rollback (-k, --commit).") list_previous_commits(service, deploy_groups, bool(given_deploy_groups), git_shas) return 1 elif commit not in git_shas and not args.force: paasta_print(PaastaColors.red("This Git SHA has never been deployed before.")) paasta_print("Please double check it or use --force to skip this verification.\n") list_previous_commits(service, deploy_groups, bool(given_deploy_groups), git_shas) return 1 returncode = 0 for deploy_group in deploy_groups: returncode = max( mark_for_deployment( git_url=git_url, service=service, deploy_group=deploy_group, commit=commit, ), returncode, ) return returncode
def paasta_rollback(args): """Call mark_for_deployment with rollback parameters :param args: contains all the arguments passed onto the script: service, deploy groups and sha. These arguments will be verified and passed onto mark_for_deployment. """ soa_dir = args.soa_dir service = figure_out_service_name(args, soa_dir) git_url = get_git_url(service, soa_dir) given_deploy_groups = { deploy_group for deploy_group in args.deploy_groups.split(",") if deploy_group } all_deploy_groups = list_deploy_groups(service=service, soa_dir=soa_dir) deploy_groups, invalid = validate_given_deploy_groups( all_deploy_groups, given_deploy_groups) if len(invalid) > 0: paasta_print( PaastaColors.yellow( "These deploy groups are not valid and will be skipped: %s.\n" % (",").join(invalid), ), ) if len(deploy_groups) == 0: paasta_print( PaastaColors.red( "ERROR: No valid deploy groups specified for %s.\n" % (service))) return 1 commit = args.commit if not commit: list_previous_commits(service, deploy_groups, bool(given_deploy_groups), soa_dir) return 1 returncode = 0 for deploy_group in deploy_groups: returncode = max( mark_for_deployment( git_url=git_url, service=service, deploy_group=deploy_group, commit=commit, ), returncode, ) return returncode
def validate_deploy_group(deploy_group, service, soa_dir): """Validate deploy_group. Raise exception if the specified deploy group is not used anywhere. """ in_use_deploy_groups = list_deploy_groups(service=service, soa_dir=soa_dir) _, invalid_deploy_groups = \ validate_given_deploy_groups(in_use_deploy_groups, [deploy_group]) if len(invalid_deploy_groups) == 1: raise DeployGroupError("ERROR: These deploy groups are not currently " "used anywhere: {}.\n" "You probably need one of these in-use deploy " "groups?:\n {}".format( ",".join(invalid_deploy_groups), ",".join(in_use_deploy_groups)))
def validate_deploy_group(deploy_group, service, soa_dir): """Validate deploy_group. Raise exception if the specified deploy group is not used anywhere. """ in_use_deploy_groups = list_deploy_groups(service=service, soa_dir=soa_dir) _, invalid_deploy_groups = \ validate_given_deploy_groups(in_use_deploy_groups, [deploy_group]) if len(invalid_deploy_groups) == 1: raise DeployGroupError("ERROR: These deploy groups are not currently " "used anywhere: {0}.\n" "You probably need one of these in-use deploy " "groups?:\n {1}".format( ",".join(invalid_deploy_groups), ",".join(in_use_deploy_groups)))
def test_list_deploy_groups_parses_configs( mock_get_instance_configs_for_service, ): mock_get_instance_configs_for_service.return_value = [ MarathonServiceConfig( service='foo', cluster='', instance='', config_dict={'deploy_group': 'fake_deploy_group'}, branch_dict=None, ), MarathonServiceConfig( service='foo', cluster='fake_cluster', instance='fake_instance', config_dict={}, branch_dict=None, ), ] actual = utils.list_deploy_groups(service="foo") assert actual == {'fake_deploy_group', 'fake_cluster.fake_instance'}
def test_list_deploy_groups_parses_configs( mock_get_instance_configs_for_service, ): mock_get_instance_configs_for_service.return_value = [ MarathonServiceConfig( service="foo", cluster="", instance="", config_dict={"deploy_group": "fake_deploy_group"}, branch_dict=None, ), MarathonServiceConfig( service="foo", cluster="fake_cluster", instance="fake_instance", config_dict={}, branch_dict=None, ), ] actual = utils.list_deploy_groups(service="foo") assert actual == {"fake_deploy_group", "fake_cluster.fake_instance"}
def paasta_rollback(args): """Call mark_for_deployment with rollback parameters :param args: contains all the arguments passed onto the script: service, deploy groups and sha. These arguments will be verified and passed onto mark_for_deployment. """ soa_dir = args.soa_dir service = figure_out_service_name(args, soa_dir) git_url = get_git_url(service, soa_dir) given_deploy_groups = {deploy_group for deploy_group in args.deploy_groups.split(",") if deploy_group} all_deploy_groups = list_deploy_groups(service=service, soa_dir=soa_dir) deploy_groups, invalid = validate_given_deploy_groups(all_deploy_groups, given_deploy_groups) if len(invalid) > 0: print PaastaColors.yellow("These deploy groups are not valid and will be skipped: %s.\n" % (",").join(invalid)) if len(deploy_groups) == 0: print PaastaColors.red("ERROR: No valid deploy groups specified for %s.\n" % (service)) return 1 commit = args.commit if not commit: list_previous_commits(service, deploy_groups, bool(given_deploy_groups), soa_dir) return 1 returncode = 0 for deploy_group in deploy_groups: returncode = max( mark_for_deployment( git_url=git_url, service=service, deploy_group=deploy_group, commit=commit, ), returncode, ) return returncode
def test_list_deploy_groups_parses_configs( mock_get_instance_configs_for_service, ): mock_get_instance_configs_for_service.return_value = [ MarathonServiceConfig( service='foo', cluster='', instance='', config_dict={'deploy_group': 'fake_deploy_group'}, branch_dict={}, ), MarathonServiceConfig( service='foo', cluster='fake_cluster', instance='fake_instance', config_dict={}, branch_dict={}, ), ] actual = utils.list_deploy_groups(service="foo") assert actual == set(['fake_deploy_group', 'fake_cluster.fake_instance'])
def get_git_shas_for_service(service, deploy_groups, soa_dir): """Returns a dictionary of 2-tuples of the form (timestamp, deploy_group) for each deploy sha""" if service is None: return [] git_url = get_git_url(service=service, soa_dir=soa_dir) all_deploy_groups = list_deploy_groups( service=service, soa_dir=soa_dir, ) deploy_groups, _ = validate_given_deploy_groups(all_deploy_groups, deploy_groups) previously_deployed_shas = {} for ref, sha in list_remote_refs(git_url).items(): regex_match = extract_tags(ref) try: deploy_group = regex_match['deploy_group'] tstamp = regex_match['tstamp'] except KeyError: pass else: # note that all strings are greater than '' if deploy_group in deploy_groups and tstamp > previously_deployed_shas.get(sha, ''): previously_deployed_shas[sha] = (tstamp, deploy_group) return previously_deployed_shas.items()
def paasta_mark_for_deployment(args): """Wrapping mark_for_deployment""" if args.verbose: log.setLevel(level=logging.DEBUG) else: log.setLevel(level=logging.INFO) service = args.service if service and service.startswith('services-'): service = service.split('services-', 1)[1] validate_service_name(service, soa_dir=args.soa_dir) in_use_deploy_groups = list_deploy_groups( service=service, soa_dir=args.soa_dir, ) _, invalid_deploy_groups = validate_given_deploy_groups(in_use_deploy_groups, [args.deploy_group]) if len(invalid_deploy_groups) == 1: paasta_print(PaastaColors.red( "ERROR: These deploy groups are not currently used anywhere: %s.\n" % (",").join(invalid_deploy_groups))) paasta_print(PaastaColors.red( "This isn't technically wrong because you can mark-for-deployment before deploying there")) paasta_print(PaastaColors.red("but this is probably a typo. Did you mean one of these in-use deploy groups?:")) paasta_print(PaastaColors.red(" %s" % (",").join(in_use_deploy_groups))) paasta_print() paasta_print(PaastaColors.red("Continuing regardless...")) if args.git_url is None: args.git_url = get_git_url(service=service, soa_dir=args.soa_dir) old_git_sha = get_currently_deployed_sha(service=service, deploy_group=args.deploy_group) if old_git_sha == args.commit: paasta_print("Warning: The sha asked to be deployed already matches what is set to be deployed:") paasta_print(old_git_sha) paasta_print("Continuing anyway.") ret = mark_for_deployment( git_url=args.git_url, deploy_group=args.deploy_group, service=service, commit=args.commit, ) if args.block: try: wait_for_deployment(service=service, deploy_group=args.deploy_group, git_sha=args.commit, soa_dir=args.soa_dir, timeout=args.timeout) line = "Deployment of {0} for {1} complete".format(args.commit, args.deploy_group) _log( service=service, component='deploy', line=line, level='event' ) except (KeyboardInterrupt, TimeoutError): if args.auto_rollback is True: if old_git_sha == args.commit: paasta_print("Error: --auto-rollback was requested, but the previous sha") paasta_print("is the same that was requested with --commit. Can't rollback") paasta_print("automatically.") else: paasta_print("Auto-Rollback requested. Marking the previous sha") paasta_print("(%s) for %s as desired." % (args.deploy_group, old_git_sha)) mark_for_deployment( git_url=args.git_url, deploy_group=args.deploy_group, service=service, commit=old_git_sha, ) else: paasta_print("Waiting for deployment aborted. PaaSTA will continue to try to deploy this code.") paasta_print("If you wish to see the status, run:") paasta_print() paasta_print(" paasta status -s %s -v" % service) paasta_print() ret = 1 except NoInstancesFound: return 1 if old_git_sha is not None and old_git_sha != args.commit and not args.auto_rollback: paasta_print() paasta_print("If you wish to roll back, you can run:") paasta_print() paasta_print(PaastaColors.bold(" paasta rollback --service %s --deploy-group %s --commit %s " % ( service, args.deploy_group, old_git_sha)) ) return ret
def paasta_rollback(args): """Call mark_for_deployment with rollback parameters :param args: contains all the arguments passed onto the script: service, deploy groups and sha. These arguments will be verified and passed onto mark_for_deployment. """ soa_dir = args.soa_dir service = figure_out_service_name(args, soa_dir) deploy_info = get_deploy_info(service=service, soa_dir=args.soa_dir) deploy_authz_check(deploy_info, service) git_url = get_git_url(service, soa_dir) given_deploy_groups = { deploy_group for deploy_group in args.deploy_groups.split(",") if deploy_group } all_deploy_groups = list_deploy_groups(service=service, soa_dir=soa_dir) deploy_groups, invalid = validate_given_deploy_groups( all_deploy_groups, given_deploy_groups ) if len(invalid) > 0: print( PaastaColors.yellow( "These deploy groups are not valid and will be skipped: %s.\n" % (",").join(invalid) ) ) if len(deploy_groups) == 0: print( PaastaColors.red( "ERROR: No valid deploy groups specified for %s.\n" % (service) ) ) return 1 git_shas = get_git_shas_for_service(service, deploy_groups, soa_dir) commit = args.commit if not commit: print("Please specify a commit to mark for rollback (-k, --commit).") list_previous_commits( service, deploy_groups, bool(given_deploy_groups), git_shas ) return 1 elif commit not in git_shas and not args.force: print(PaastaColors.red("This Git SHA has never been deployed before.")) print("Please double check it or use --force to skip this verification.\n") list_previous_commits( service, deploy_groups, bool(given_deploy_groups), git_shas ) return 1 returncode = 0 for deploy_group in deploy_groups: rolled_back_from = get_currently_deployed_sha(service, deploy_group) returncode |= mark_for_deployment( git_url=git_url, service=service, deploy_group=deploy_group, commit=commit ) # we could also gate this by the return code from m-f-d, but we probably care more about someone wanting to # rollback than we care about if the underlying machinery was successfully able to complete the request if rolled_back_from != commit: audit_action_details = { "rolled_back_from": rolled_back_from, "rolled_back_to": commit, "rollback_type": RollbackTypes.USER_INITIATED_ROLLBACK.value, "deploy_group": deploy_group, } _log_audit( action="rollback", action_details=audit_action_details, service=service ) return returncode
def paasta_mark_for_deployment(args): """Wrapping mark_for_deployment""" if args.verbose: log.setLevel(level=logging.DEBUG) else: log.setLevel(level=logging.INFO) service = args.service if service and service.startswith('services-'): service = service.split('services-', 1)[1] validate_service_name(service, soa_dir=args.soa_dir) in_use_deploy_groups = list_deploy_groups( service=service, soa_dir=args.soa_dir, ) _, invalid_deploy_groups = validate_given_deploy_groups( in_use_deploy_groups, [args.deploy_group]) if len(invalid_deploy_groups) == 1: paasta_print( PaastaColors.red( "ERROR: These deploy groups are not currently used anywhere: %s.\n" % (",").join(invalid_deploy_groups), )) paasta_print( PaastaColors.red( "This isn't technically wrong because you can mark-for-deployment before deploying there", )) paasta_print( PaastaColors.red( "but this is probably a typo. Did you mean one of these in-use deploy groups?:" )) paasta_print( PaastaColors.red(" %s" % (",").join(in_use_deploy_groups))) paasta_print() paasta_print(PaastaColors.red("Continuing regardless...")) if args.git_url is None: args.git_url = get_git_url(service=service, soa_dir=args.soa_dir) try: validate_full_git_sha(args.commit) except ArgumentTypeError: refs = remote_git.list_remote_refs(args.git_url) commits = short_to_full_git_sha(short=args.commit, refs=refs) if len(commits) != 1: raise ValueError( "%s matched %d git shas (with refs pointing at them). Must match exactly 1." % (args.commit, len(commits)), ) args.commit = commits[0] old_git_sha = get_currently_deployed_sha(service=service, deploy_group=args.deploy_group) if old_git_sha == args.commit: paasta_print( "Warning: The sha asked to be deployed already matches what is set to be deployed:" ) paasta_print(old_git_sha) paasta_print("Continuing anyway.") if args.verify_image: if not is_docker_image_already_in_registry(service, args.soa_dir, args.commit): raise ValueError( 'Failed to find image in the registry for the following sha %s' % args.commit) ret = mark_for_deployment( git_url=args.git_url, deploy_group=args.deploy_group, service=service, commit=args.commit, ) if args.block and ret == 0: try: wait_for_deployment( service=service, deploy_group=args.deploy_group, git_sha=args.commit, soa_dir=args.soa_dir, timeout=args.timeout, ) line = "Deployment of {} for {} complete".format( args.commit, args.deploy_group) _log( service=service, component='deploy', line=line, level='event', ) except (KeyboardInterrupt, TimeoutError): if args.auto_rollback is True: if old_git_sha == args.commit: paasta_print( "Error: --auto-rollback was requested, but the previous sha" ) paasta_print( "is the same that was requested with --commit. Can't rollback" ) paasta_print("automatically.") else: paasta_print( "Auto-Rollback requested. Marking the previous sha") paasta_print("(%s) for %s as desired." % (args.deploy_group, old_git_sha)) mark_for_deployment( git_url=args.git_url, deploy_group=args.deploy_group, service=service, commit=old_git_sha, ) else: report_waiting_aborted(service, args.deploy_group) ret = 1 except NoSuchCluster: report_waiting_aborted(service, args.deploy_group) if old_git_sha is not None and old_git_sha != args.commit and not args.auto_rollback: paasta_print() paasta_print("If you wish to roll back, you can run:") paasta_print() paasta_print( PaastaColors.bold( " paasta rollback --service %s --deploy-group %s --commit %s " % ( service, args.deploy_group, old_git_sha, )), ) return ret
def paasta_mark_for_deployment(args): """Wrapping mark_for_deployment""" if args.verbose: log.setLevel(level=logging.DEBUG) else: log.setLevel(level=logging.INFO) service = args.service if service and service.startswith('services-'): service = service.split('services-', 1)[1] validate_service_name(service, soa_dir=args.soa_dir) in_use_deploy_groups = list_deploy_groups( service=service, soa_dir=args.soa_dir, ) _, invalid_deploy_groups = validate_given_deploy_groups( in_use_deploy_groups, [args.deploy_group]) if len(invalid_deploy_groups) == 1: paasta_print( PaastaColors.red( "ERROR: These deploy groups are not currently used anywhere: %s.\n" % (",").join(invalid_deploy_groups))) paasta_print( PaastaColors.red( "This isn't technically wrong because you can mark-for-deployment before deploying there" )) paasta_print( PaastaColors.red( "but this is probably a typo. Did you mean one of these in-use deploy groups?:" )) paasta_print( PaastaColors.red(" %s" % (",").join(in_use_deploy_groups))) paasta_print() paasta_print(PaastaColors.red("Continuing regardless...")) if args.git_url is None: args.git_url = get_git_url(service=service, soa_dir=args.soa_dir) old_git_sha = get_currently_deployed_sha(service=service, deploy_group=args.deploy_group) if old_git_sha == args.commit: paasta_print( "Warning: The sha asked to be deployed already matches what is set to be deployed:" ) paasta_print(old_git_sha) paasta_print("Continuing anyway.") ret = mark_for_deployment( git_url=args.git_url, deploy_group=args.deploy_group, service=service, commit=args.commit, ) if args.block: try: wait_for_deployment(service=service, deploy_group=args.deploy_group, git_sha=args.commit, soa_dir=args.soa_dir, timeout=args.timeout) line = "Deployment of {} for {} complete".format( args.commit, args.deploy_group) _log(service=service, component='deploy', line=line, level='event') except (KeyboardInterrupt, TimeoutError): if args.auto_rollback is True: if old_git_sha == args.commit: paasta_print( "Error: --auto-rollback was requested, but the previous sha" ) paasta_print( "is the same that was requested with --commit. Can't rollback" ) paasta_print("automatically.") else: paasta_print( "Auto-Rollback requested. Marking the previous sha") paasta_print("(%s) for %s as desired." % (args.deploy_group, old_git_sha)) mark_for_deployment( git_url=args.git_url, deploy_group=args.deploy_group, service=service, commit=old_git_sha, ) else: paasta_print( "Waiting for deployment aborted. PaaSTA will continue to try to deploy this code." ) paasta_print("If you wish to see the status, run:") paasta_print() paasta_print(" paasta status -s %s -v" % service) paasta_print() ret = 1 except NoInstancesFound: return 1 if old_git_sha is not None and old_git_sha != args.commit and not args.auto_rollback: paasta_print() paasta_print("If you wish to roll back, you can run:") paasta_print() paasta_print( PaastaColors.bold( " paasta rollback --service %s --deploy-group %s --commit %s " % (service, args.deploy_group, old_git_sha))) return ret
def paasta_mark_for_deployment(args): """Wrapping mark_for_deployment""" if args.verbose: log.setLevel(level=logging.DEBUG) else: log.setLevel(level=logging.INFO) service = args.service if service and service.startswith('services-'): service = service.split('services-', 1)[1] validate_service_name(service, soa_dir=args.soa_dir) deploy_group = args.deploy_group in_use_deploy_groups = list_deploy_groups( service=service, soa_dir=args.soa_dir, ) _, invalid_deploy_groups = validate_given_deploy_groups( in_use_deploy_groups, [deploy_group]) if len(invalid_deploy_groups) == 1: paasta_print( PaastaColors.red( "ERROR: These deploy groups are not currently used anywhere: %s.\n" % (",").join(invalid_deploy_groups), )) paasta_print( PaastaColors.red( "This isn't technically wrong because you can mark-for-deployment before deploying there", )) paasta_print( PaastaColors.red( "but this is probably a typo. Did you mean one of these in-use deploy groups?:" )) paasta_print( PaastaColors.red(" %s" % (",").join(in_use_deploy_groups))) paasta_print() paasta_print(PaastaColors.red("Continuing regardless...")) if args.git_url is None: args.git_url = get_git_url(service=service, soa_dir=args.soa_dir) commit = validate_git_sha(sha=args.commit, git_url=args.git_url) old_git_sha = get_currently_deployed_sha(service=service, deploy_group=deploy_group) if old_git_sha == commit: paasta_print( "Warning: The sha asked to be deployed already matches what is set to be deployed:" ) paasta_print(old_git_sha) paasta_print("Continuing anyway.") if args.verify_image: if not is_docker_image_already_in_registry(service, args.soa_dir, commit): raise ValueError( 'Failed to find image in the registry for the following sha %s' % commit) deploy_info = get_deploy_info(service=service, soa_dir=args.soa_dir) slack_notifier = SlackDeployNotifier( deploy_info=deploy_info, service=service, deploy_group=deploy_group, commit=commit, old_commit=old_git_sha, git_url=args.git_url, ) ret = mark_for_deployment( git_url=args.git_url, deploy_group=deploy_group, service=service, commit=commit, ) slack_notifier.notify_after_mark(ret=ret) if args.block and ret == 0: try: wait_for_deployment( service=service, deploy_group=deploy_group, git_sha=commit, soa_dir=args.soa_dir, timeout=args.timeout, ) line = f"Deployment of {commit} for {deploy_group} complete" _log( service=service, component='deploy', line=line, level='event', ) slack_notifier.notify_after_good_deploy() except (KeyboardInterrupt, TimeoutError): if args.auto_rollback is True: if old_git_sha == commit: paasta_print( "Error: --auto-rollback was requested, but the previous sha" ) paasta_print( "is the same that was requested with --commit. Can't rollback" ) paasta_print("automatically.") else: paasta_print( "Auto-Rollback requested. Marking the previous sha") paasta_print( f"({deploy_group}) for {old_git_sha} as desired.") mark_for_deployment( git_url=args.git_url, deploy_group=deploy_group, service=service, commit=old_git_sha, ) slack_notifier.notify_after_auto_rollback() else: report_waiting_aborted(service, deploy_group) slack_notifier.notify_after_abort() ret = 1 except NoSuchCluster: report_waiting_aborted(service, deploy_group) slack_notifier.notify_after_abort() if old_git_sha is not None and old_git_sha != commit and not args.auto_rollback: paasta_print() paasta_print("If you wish to roll back, you can run:") paasta_print() paasta_print( PaastaColors.bold( " paasta rollback --service {} --deploy-group {} --commit {} " .format( service, deploy_group, old_git_sha, )), ) return ret
def paasta_mark_for_deployment(args): """Wrapping mark_for_deployment""" if args.verbose: log.setLevel(level=logging.DEBUG) else: log.setLevel(level=logging.INFO) service = args.service if service and service.startswith('services-'): service = service.split('services-', 1)[1] validate_service_name(service, soa_dir=args.soa_dir) in_use_deploy_groups = list_deploy_groups( service=service, soa_dir=args.soa_dir, ) _, invalid_deploy_groups = validate_given_deploy_groups( in_use_deploy_groups, [args.deploy_group]) if len(invalid_deploy_groups) == 1: print PaastaColors.red( "ERROR: These deploy groups are not currently used anywhere: %s.\n" % (",").join(invalid_deploy_groups)) print PaastaColors.red( "This isn't technically wrong because you can mark-for-deployment before deploying there" ) print PaastaColors.red( "but this is probably a typo. Did you mean one of these in-use deploy groups?:" ) print PaastaColors.red(" %s" % (",").join(in_use_deploy_groups)) print "" print PaastaColors.red("Continuing regardless...") if args.git_url is None: args.git_url = get_git_url(service=service, soa_dir=args.soa_dir) old_git_sha = get_currently_deployed_sha(service=service, deploy_group=args.deploy_group) if old_git_sha == args.commit: print "Warning: The sha asked to be deployed already matches what is set to be deployed:" print old_git_sha print "Continuing anyway." ret = mark_for_deployment( git_url=args.git_url, deploy_group=args.deploy_group, service=service, commit=args.commit, ) if args.block: try: print "Waiting for deployment of {0} for '{1}' complete...".format( args.commit, args.deploy_group) wait_for_deployment(service=service, deploy_group=args.deploy_group, git_sha=args.commit, soa_dir=args.soa_dir, timeout=args.timeout) line = "Deployment of {0} for {1} complete".format( args.commit, args.deploy_group) _log(service=service, component='deploy', line=line, level='event') except (KeyboardInterrupt, TimeoutError): print "Waiting for deployment aborted. PaaSTA will continue to try to deploy this code." print "If you wish to see the status, run:" print "" print " paasta status -s %s -v" % service print "" ret = 1 if old_git_sha is not None and old_git_sha != args.commit: print "" print "If you wish to roll back, you can run:" print "" print PaastaColors.bold( " paasta rollback --service %s --deploy-group %s --commit %s " % (service, args.deploy_group, old_git_sha)) return ret
def paasta_mark_for_deployment(args): """Wrapping mark_for_deployment""" if args.verbose: log.setLevel(level=logging.DEBUG) else: log.setLevel(level=logging.INFO) service = args.service if service and service.startswith("services-"): service = service.split("services-", 1)[1] validate_service_name(service, soa_dir=args.soa_dir) deploy_group = args.deploy_group in_use_deploy_groups = list_deploy_groups(service=service, soa_dir=args.soa_dir) _, invalid_deploy_groups = validate_given_deploy_groups( in_use_deploy_groups, [deploy_group] ) if len(invalid_deploy_groups) == 1: paasta_print( PaastaColors.red( "ERROR: These deploy groups are not currently used anywhere: %s.\n" % (",").join(invalid_deploy_groups) ) ) paasta_print( PaastaColors.red( "This isn't technically wrong because you can mark-for-deployment before deploying there" ) ) paasta_print( PaastaColors.red( "but this is probably a typo. Did you mean one of these in-use deploy groups?:" ) ) paasta_print(PaastaColors.red(" %s" % (",").join(in_use_deploy_groups))) paasta_print() paasta_print(PaastaColors.red("Continuing regardless...")) if args.git_url is None: args.git_url = get_git_url(service=service, soa_dir=args.soa_dir) commit = validate_git_sha(sha=args.commit, git_url=args.git_url) old_git_sha = get_currently_deployed_sha(service=service, deploy_group=deploy_group) if old_git_sha == commit: paasta_print( "Warning: The sha asked to be deployed already matches what is set to be deployed:" ) paasta_print(old_git_sha) paasta_print("Continuing anyway.") if args.verify_image: if not is_docker_image_already_in_registry(service, args.soa_dir, commit): raise ValueError( "Failed to find image in the registry for the following sha %s" % commit ) deploy_info = get_deploy_info(service=service, soa_dir=args.soa_dir) deploy_process = MarkForDeploymentProcess( service=service, deploy_info=deploy_info, deploy_group=deploy_group, commit=commit, old_git_sha=old_git_sha, git_url=args.git_url, auto_rollback=args.auto_rollback, block=args.block, soa_dir=args.soa_dir, timeout=args.timeout, auto_certify_delay=args.auto_certify_delay, auto_abandon_delay=args.auto_abandon_delay, auto_rollback_delay=args.auto_rollback_delay, ) ret = deploy_process.run() return ret
def paasta_rollback(args: argparse.Namespace) -> int: """Call mark_for_deployment with rollback parameters :param args: contains all the arguments passed onto the script: service, deploy groups and sha. These arguments will be verified and passed onto mark_for_deployment. """ soa_dir = args.soa_dir service = figure_out_service_name(args, soa_dir) deploy_info = get_deploy_info(service=service, soa_dir=args.soa_dir) if not can_user_deploy_service(deploy_info, service): return 1 git_url = get_git_url(service, soa_dir) if args.all_deploy_groups: given_deploy_groups = list_deploy_groups(service=service, soa_dir=soa_dir) else: given_deploy_groups = { deploy_group for deploy_group in args.deploy_groups.split(",") if deploy_group } all_deploy_groups = list_deploy_groups(service=service, soa_dir=soa_dir) deploy_groups, invalid = validate_given_deploy_groups( all_deploy_groups, given_deploy_groups) if len(invalid) > 0: print( PaastaColors.yellow( "These deploy groups are not valid and will be skipped: %s.\n" % (",").join(invalid))) if len(deploy_groups) == 0 and not args.all_deploy_groups: print( PaastaColors.red( "ERROR: No valid deploy groups specified for %s.\n Use the flag -a to rollback all valid deploy groups for this service" % (service))) return 1 versions = get_versions_for_service(service, deploy_groups, soa_dir) commit = args.commit image_version = args.image_version new_version = DeploymentVersion(sha=commit, image_version=image_version) if not commit: print("Please specify a commit to mark for rollback (-k, --commit).") list_previous_versions(service, deploy_groups, bool(given_deploy_groups), versions) return 1 elif new_version not in versions and not args.force: print( PaastaColors.red( f"This version {new_version} has never been deployed before.")) print( "Please double check it or use --force to skip this verification.\n" ) list_previous_versions(service, deploy_groups, bool(given_deploy_groups), versions) return 1 # TODO: Add similar check for when image_version is empty and no-commit redeploys is enforced for requested deploy_group returncode = 0 for deploy_group in deploy_groups: rolled_back_from = get_currently_deployed_version( service, deploy_group) returncode |= mark_for_deployment( git_url=git_url, service=service, deploy_group=deploy_group, commit=commit, image_version=image_version, ) # we could also gate this by the return code from m-f-d, but we probably care more about someone wanting to # rollback than we care about if the underlying machinery was successfully able to complete the request if rolled_back_from != new_version: audit_action_details = { "rolled_back_from": str(rolled_back_from), "rolled_back_to": str(new_version), "rollback_type": RollbackTypes.USER_INITIATED_ROLLBACK.value, "deploy_group": deploy_group, } _log_audit(action="rollback", action_details=audit_action_details, service=service) return returncode