예제 #1
0
def shell_command(command: str,
                  console: Console,
                  exit_on_returncode=True,
                  display_stderr=True,
                  allow_stdin=False):
    try:
        stdin_ = DEVNULL
        if allow_stdin:
            stdin_ = None

        stderr_ = None
        if not display_stderr:
            stderr_ = DEVNULL

        console.debug("Starting shell command: " + command)
        returncode = call(command, shell=True, stdin=stdin_, stderr=stderr_)
        if returncode != 0 and exit_on_returncode:
            exit(returncode)

    except KeyboardInterrupt:
        exit()
예제 #2
0
def main():
    '''
    This is main
    '''
    context = Context(constants.ARGUMENTS_DEFINITION)
    context.load_context_from_command_line(argv)

    console = Console(context.quiet, context.verbose, context.ansi)

    valid_configuration_file = find_configuration_file(
        context.configuration_file)
    if valid_configuration_file is not None:
        console.debug("Using configuration file " + valid_configuration_file)
        try:
            profiles = toml.load(valid_configuration_file)
        except toml.decoder.TomlDecodeError as err:
            console.error(
                "An error occured while loading the configuration file:")
            console.error(str(err))
            exit(2)
    else:
        console.warning(
            "Configuration file '{}' was not found in either the current directory, home directory or any of these locations:\n{}"
            .format(context.configuration_file,
                    get_default_configuration_locations()))
        exit(2)

    base_dir = dirname(valid_configuration_file)
    # todo: allow group of groups
    groups = Groups(profiles)
    if groups.exists(context.profile_name):
        group_name = context.profile_name
        for profile_name in groups.get_profiles(context.profile_name):
            console.debug("Starting profile [{}] from group [{}]".format(
                profile_name, group_name))
            context.profile_name = profile_name
            run_restic(base_dir, context, profiles, console)
    else:
        # single profile
        run_restic(base_dir, context, profiles, console)
예제 #3
0
def run_restic(base_dir: str, context: Context, profiles: dict,
               console: Console):
    file_search = FileSearch(base_dir)
    config = Config(profiles, file_search)
    profile = Profile(config, context.profile_name)
    restic = Restic()
    if context.args:
        # A command was passed as an argument (it has to be the first one after the options)
        restic.command = context.args[0]

    # Build list of arguments to pass to restic
    if constants.SECTION_CONFIGURATION_GLOBAL in profiles:
        context.set_global_context(config)

    try:
        if context.profile_name in profiles:
            profile.set_common_configuration()

            # there's no default command yet
            if not restic.command:
                restic.command = context.default_command

            # we might need the init command so we prepare it
            profile.set_command_configuration('init')

            # we might also need the check command
            profile.set_command_configuration('check')

            # if the command is backup, we need to load the retention model
            if restic.command == constants.COMMAND_BACKUP:
                profile.set_retention_configuration()

            profile.set_command_configuration(restic.command)

            # environment variables
            env = config.get_environment(context.profile_name)
            if env:
                for key, value in env.items():
                    console.debug(
                        "Setting environment variable {}".format(key))
                    # When running a group of backups, we might want to put back/remove the environment variable after
                    environ[key] = value

        profile.set_verbosity(context.quiet, context.verbose)
        restic.extend_arguments(profile.get_command_flags(restic.command))

    except FileNotFoundError as error:
        console.error("Error in profile [{}]: {}".format(
            context.profile_name, str(error)))
        exit(2)

    except ConfigError as error:
        console.error("Error in profile [{}]: {}".format(
            error.section, error.message))
        exit(2)

    # check that we have the minimum information we need
    if not profile.repository:
        console.error(
            "Error in profile [{}]: a repository is needed in the configuration."
            .format(context.profile_name))
        exit(2)

    # this is the leftover from the command line
    restic.extend_arguments(context.args[1:])

    if profile.initialize:
        initialize_repository(context, profile, console)

    if profile.run_before:
        run_commands(profile.run_before, console)

    if profile.check_before:
        check(context, profile, console)

    if profile.forget_before:
        cleanup_old_backups(context, profile, console)

    restic_command(context, restic, profile, console)

    if profile.forget_after:
        cleanup_old_backups(context, profile, console)

    if profile.check_after:
        check(context, profile, console)

    if profile.run_after:
        run_commands(profile.run_after, console)