Beispiel #1
0
def announce_deploy_start(environment, service_name):
    send_email(
        environment,
        subject="{user} has initiated a {system_name} deploy to {environment}".format(
            user=get_default_username(),
            system_name=service_name,
            environment=environment.meta_config.deploy_env,
        ),
    )
Beispiel #2
0
 def _announce_formplayer_deploy_start(environment):
     mail_admins(
         environment,
         subject="{user} has initiated a formplayer deploy to {environment}.".format(
             user=get_default_username(),
             environment=environment.meta_config.deploy_env,
         ),
         message='',
     )
Beispiel #3
0
    def get_diff_context(self):
        context = {
            "new_version_details": self.new_version_details,
            "user": get_default_username(),
            "LABELS_TO_EXPAND": LABELS_TO_EXPAND,
            "errors": [],
            "warnings": []
        }

        if self.deployed_commit_matches_latest_commit:
            context["errors"].append(
                "Versions are identical. No changes since last deploy.")
            return context

        if not (self.current_commit and self.deploy_commit):
            context["warnings"].append("Insufficient info to get deploy diff.")
            return context

        context["compare_url"] = self.url

        if not self.generate_diff:
            disabled_msg = "Deploy diffs disabled for this environment."
            print(color_warning(disabled_msg))
            context["warnings"].append(disabled_msg)
            return context

        if not self.repo.permissions:
            # using unauthenticated API calls, skip diff creation to avoid hitting rate limits
            print(
                color_warning(
                    "Diff generation skipped. Supply a Github token to see deploy diffs."
                ))
            context["warnings"].append("Diff omitted.")
            return context

        try:
            pr_numbers = self._get_pr_numbers()
        except GithubException as e:
            print(color_error(f"Error getting diff commits: {e}"))
            context["warnings"].append(
                "There was an error fetching the PRs since the last deploy.")
            return context

        if len(pr_numbers) > 500:
            context["warnings"].append("There are too many PRs to display.")
            return context
        elif not pr_numbers:
            context["warnings"].append("No PRs merged since last release.")
            return context

        pool = Pool(5)
        pr_infos = [_f for _f in pool.map(self._get_pr_info, pr_numbers) if _f]

        context["pr_infos"] = pr_infos
        prs_by_label = self._get_prs_by_label(pr_infos)
        context["prs_by_label"] = prs_by_label
        return context
Beispiel #4
0
    def run(self, args, unknown_args):
        environment = get_environment(args.env_name)
        run_dir = environment.paths.get_env_file_path('.generated-terraform')
        modules_dir = os.path.join(TERRAFORM_DIR, 'modules')
        modules_dest = os.path.join(run_dir, 'modules')
        if not os.path.isdir(run_dir):
            os.mkdir(run_dir)
        if not os.path.isdir(run_dir):
            os.mkdir(run_dir)
        if not (os.path.exists(modules_dest)
                and os.readlink(modules_dest) == modules_dir):
            os.symlink(modules_dir, modules_dest)

        if args.username != get_default_username():
            print_help_message_about_the_commcare_cloud_default_username_env_var(
                args.username)

        key_name = args.username

        try:
            generate_terraform_entrypoint(
                environment,
                key_name,
                run_dir,
                apply_immediately=args.apply_immediately)
        except UnauthorizedUser as e:
            allowed_users = environment.users_config.dev_users.present
            puts(
                color_error(
                    "Unauthorized user {}.\n\n"
                    "Use COMMCARE_CLOUD_DEFAULT_USERNAME or --username to pass in one of the allowed ssh users:{}"
                    .format(e.username, '\n  - '.join([''] + allowed_users))))
            return -1

        if not args.skip_secrets and unknown_args and unknown_args[0] in (
                'plan', 'apply'):
            rds_password = (environment.get_vault_variables()['secrets']
                            ['POSTGRES_USERS']['root']['password'] if
                            environment.terraform_config.rds_instances else '')

            with open(os.path.join(run_dir, 'secrets.auto.tfvars'), 'w') as f:
                print('rds_password = {}'.format(json.dumps(rds_password)),
                      file=f)

        env_vars = {'AWS_PROFILE': aws_sign_in(environment)}
        all_env_vars = os.environ.copy()
        all_env_vars.update(env_vars)
        cmd_parts = ['terraform'] + unknown_args
        cmd = ' '.join(shlex_quote(arg) for arg in cmd_parts)
        print_command('cd {}; {} {}; cd -'.format(
            run_dir,
            ' '.join('{}={}'.format(key, value)
                     for key, value in env_vars.items()),
            cmd,
        ))
        return subprocess.call(cmd, shell=True, env=all_env_vars, cwd=run_dir)
Beispiel #5
0
def call_record_deploy_success(environment, diff, start_time, end_time):
    delta = end_time - start_time
    args = [
        '--user', get_default_username(),
        '--environment', environment.meta_config.deploy_env,
        '--url', diff.url,
        '--minutes', str(int(delta.total_seconds() // 60)),
        '--commit', diff.deploy_commit,
    ]
    commcare_cloud(environment.name, 'django-manage', 'record_deploy_success', *args)
Beispiel #6
0
def get_server_address(environment, group):
    host_group = split_host_group(group)
    username, group, index = host_group.user, host_group.group, host_group.index

    if ':' in group:
        display.warning(
            "Use '[x]' to select hosts instead of ':x' which has been deprecated."
        )
        group, index = group.rsplit(':', 1)
        try:
            index = int(index)
        except (TypeError, ValueError):
            raise HostMatchException(
                "Non-numeric group index: {}".format(index))

    if not username:
        default_username = get_default_username()
        if default_username.is_guess:
            username = ""
        else:
            username = "******".format(default_username)

    if re.match(r'(\d+\.?){4}', group):
        # short circuit for IP addresses
        return username + group

    try:
        servers = get_instance_group(environment, group)
    except IOError as err:
        raise HostMatchException(err)
    except KeyError:
        raise HostMatchException(
            "Unknown server name/group: {}\n".format(group))

    if index is not None and index > len(servers) - 1:
        raise HostMatchException(
            "Invalid group index: {index}\n"
            "Please specify a number between 0 and {max} inclusive\n".format(
                index=index, max=len(servers) - 1))
    if len(servers) > 1:
        if index is None:
            raise HostMatchException(
                "There are {num} servers in the '{group}' group\n"
                "Please specify the index of the server. Example: {group}:0\n".
                format(num=len(servers), group=group))
        server = servers[index]
    else:
        server = servers[index or 0]

    return username + server
Beispiel #7
0
    def run(self, args, unknown_args):
        environment = get_environment(args.env_name)
        run_dir = environment.paths.get_env_file_path('.generated-terraform')
        modules_dir = os.path.join(TERRAFORM_DIR, 'modules')
        modules_dest = os.path.join(run_dir, 'modules')
        if not os.path.isdir(run_dir):
            os.mkdir(run_dir)
        if not os.path.isdir(run_dir):
            os.mkdir(run_dir)
        if not (os.path.exists(modules_dest) and os.readlink(modules_dest) == modules_dir):
            os.symlink(modules_dir, modules_dest)

        if args.username != get_default_username():
            print_help_message_about_the_commcare_cloud_default_username_env_var(args.username)

        key_name = args.username

        try:
            generate_terraform_entrypoint(environment, key_name, run_dir,
                                          apply_immediately=args.apply_immediately)
        except UnauthorizedUser as e:
            allowed_users = environment.users_config.dev_users.present
            puts(colored.red(
                "Unauthorized user {}.\n\n"
                "Use COMMCARE_CLOUD_DEFAULT_USERNAME or --username to pass in one of the allowed ssh users:{}"
                .format(e.username, '\n  - '.join([''] + allowed_users))))
            return -1

        if not args.skip_secrets and unknown_args and unknown_args[0] in ('plan', 'apply'):
            rds_password = (
                environment.get_vault_variables()['secrets']['POSTGRES_USERS']['root']['password']
                if environment.terraform_config.rds_instances
                else ''
            )

            with open(os.path.join(run_dir, 'secrets.auto.tfvars'), 'w') as f:
                print('rds_password = {}'.format(json.dumps(rds_password)), file=f)

        env_vars = {'AWS_PROFILE': aws_sign_in(environment.terraform_config.aws_profile)}
        all_env_vars = os.environ.copy()
        all_env_vars.update(env_vars)
        cmd_parts = ['terraform'] + unknown_args
        cmd = ' '.join(shlex_quote(arg) for arg in cmd_parts)
        print_command('cd {}; {} {}; cd -'.format(
            run_dir,
            ' '.join('{}={}'.format(key, value) for key, value in env_vars.items()),
            cmd,
        ))
        return subprocess.call(cmd, shell=True, env=all_env_vars, cwd=run_dir)
def record_deploy_in_datadog(environment, diff, tdelta):
    if environment.public_vars.get('DATADOG_ENABLED', False):
        print(color_summary(f">> Recording deploy in Datadog"))
        diff_url = f"\nDiff link: [Git Diff]({diff.url})"
        deploy_notification_text = (
            "Formplayer has been successfully deployed to "
            "*{}* by *{}* in *{}* minutes.\nRelease Name: {}{}".format(
                environment.name, get_default_username(),
                int(tdelta.total_seconds() / 60) or '?',
                environment.new_release_name(), diff_url))
        commcare_cloud(environment.name,
                       'send-datadog-event',
                       'Formplayer Deploy Success',
                       deploy_notification_text,
                       '--alert_type',
                       "success",
                       show_command=False)
def get_server_address(environment, group, exit=sys.exit):
    if "@" in group:
        username, group = group.split('@', 1)
        username += "@"
    else:
        default_username = get_default_username()
        if default_username.is_guess:
            username = ""
        else:
            username = "******".format(default_username)

    if re.match(r'(\d+\.?){4}', group):
        # short circuit for IP addresses
        return username + group

    if ':' in group:
        group, index = group.rsplit(':', 1)
        try:
            index = int(index)
        except (TypeError, ValueError):
            exit("Non-numeric group index: {}".format(index))
    else:
        index = None

    try:
        servers = get_instance_group(environment, group)
    except IOError as err:
        exit(err)
    except KeyError as err:
        exit("Unknown server name/group: {}\n".format(group))

    if index is not None and index > len(servers) - 1:
        exit("Invalid group index: {index}\n"
             "Please specify a number between 0 and {max} inclusive\n".format(
                 index=index, max=len(servers) - 1))
    if len(servers) > 1:
        if index is None:
            exit(
                "There are {num} servers in the '{group}' group\n"
                "Please specify the index of the server. Example: {group}:0\n".
                format(num=len(servers), group=group))
        server = servers[index]
    else:
        server = servers[index or 0]

    return username + server
Beispiel #10
0
class Terraform(CommandBase):
    command = 'terraform'
    help = "Run terraform for this env with the given arguments"

    arguments = (
        Argument('--skip-secrets',
                 action='store_true',
                 help="""
            Skip regenerating the secrets file.

            Good for not having to enter vault password again.
        """),
        Argument('--username',
                 default=get_default_username(),
                 help="""
            The username of the user whose public key will be put on new servers.

            Normally this would be _your_ username.
            Defaults to the value of the COMMCARE_CLOUD_DEFAULT_USERNAME environment variable
            or else the username of the user running the command.
        """),
    )

    def run(self, args, unknown_args):
        environment = get_environment(args.env_name)
        run_dir = environment.paths.get_env_file_path('.generated-terraform')
        modules_dir = os.path.join(TERRAFORM_DIR, 'modules')
        modules_dest = os.path.join(run_dir, 'modules')
        if not os.path.isdir(run_dir):
            os.mkdir(run_dir)
        if not os.path.isdir(run_dir):
            os.mkdir(run_dir)
        if not (os.path.exists(modules_dest)
                and os.readlink(modules_dest) == modules_dir):
            os.symlink(modules_dir, modules_dest)

        if args.username != get_default_username():
            print_help_message_about_the_commcare_cloud_default_username_env_var(
                args.username)

        key_name = args.username

        try:
            generate_terraform_entrypoint(environment, key_name, run_dir)
        except UnauthorizedUser as e:
            allowed_users = environment.users_config.dev_users.present
            puts(
                colored.red(
                    "Unauthorized user {}.\n\n"
                    "Use COMMCARE_CLOUD_DEFAULT_USERNAME or --username to pass in one of the allowed ssh users:{}"
                    .format(e.username, '\n  - '.join([''] + allowed_users))))
            return -1

        if not args.skip_secrets and unknown_args and unknown_args[0] in (
                'plan', 'apply'):
            rds_password = environment.get_vault_variables(
            )['secrets']['POSTGRES_USERS']['root']['password']
            with open(os.path.join(run_dir, 'secrets.auto.tfvars'), 'w') as f:
                print('rds_password = {}'.format(json.dumps(rds_password)),
                      file=f)

        env_vars = {
            'AWS_PROFILE':
            aws_sign_in(environment.terraform_config.aws_profile)
        }
        all_env_vars = os.environ.copy()
        all_env_vars.update(env_vars)
        cmd_parts = ['terraform'] + unknown_args
        cmd = ' '.join(shlex_quote(arg) for arg in cmd_parts)
        print_command('cd {}; {} {}; cd -'.format(
            run_dir,
            ' '.join('{}={}'.format(key, value)
                     for key, value in env_vars.items()),
            cmd,
        ))
        return subprocess.call(cmd, shell=True, env=all_env_vars, cwd=run_dir)