Esempio n. 1
0
 def setUpClass(cls):
     cls.config_data = read_config('tests/fixtures/dupcomposer-config.yml')
     cls.config_provider_s3 = (cls.config_data['backup_groups']
                               ['my_s3_backups']['backup_provider'])
     cls.config_provider_s3_boto3 = (
         cls.config_data['backup_groups']['my_s3_boto3_backups']
         ['backup_provider'])
Esempio n. 2
0
 def setUpClass(cls):
     cls.config_data = read_config('tests/fixtures/dupcomposer-config.yml')
     cls.config_provider_scp = (cls.config_data['backup_groups']
                                ['my_scp_backups']['backup_provider'])
     cls.config_provider_scp_nopass = cls.config_provider_scp.copy()
     del cls.config_provider_scp_nopass['password']
     cls.config_provider_sftp = {
         'url': 'sftp://[email protected]/',
         'password': '******'
     }
Esempio n. 3
0
 def setUpClass(cls):
     cls.config_data = read_config('tests/fixtures/dupcomposer-config.yml')
     cls.config_with_keyring = \
         {'encryption':
          {'enabled': False},
          'backup_provider': {'url': 'scp://[email protected]/',
                              'password': ['service', 'account']},
          'volume_size': 200,
          'sources': {'/home/fun':
                      {'backup_path': '/home/fun', 'restore_path': '/root/restored'}}
         }
     cls.backup_groups = {}
Esempio n. 4
0
 def setUpClass(cls):
     cls.config_data = read_config('tests/fixtures/dupcomposer-config.yml')
     cls.config_provider_local = (cls.config_data['backup_groups']
                                  ['my_local_backups']['backup_provider'])
     cls.config_provider_s3 = (cls.config_data['backup_groups']
                               ['my_s3_backups']['backup_provider'])
     cls.config_provider_scp = (cls.config_data['backup_groups']
                                ['my_scp_backups']['backup_provider'])
     cls.config_provider_sftp = {
         'url': 'sftp://[email protected]',
         'password': '******'
     }
Esempio n. 5
0
 def setUpClass(cls):
     cls.config_data = read_config('tests/fixtures/dupcomposer-config.yml')
     cls.config_encryption_off = (
         cls.config_data['backup_groups']['my_local_backups']['encryption'])
     cls.config_encryption_on = (
         cls.config_data['backup_groups']['my_s3_backups']['encryption'])
     cls.config_with_keyring = {
         'enabled': True,
         'gpg_key': 'xxxxxx',
         'gpg_passphrase': ['service', 'account']
     }
     cls.config_with_keyring_invalid = {
         'enabled': True,
         'gpg_key': 'xxx',
         'gpg_passphrase': [1, 2, 3]
     }
Esempio n. 6
0
 def setUpClass(cls):
     cls.config_data = read_config('tests/fixtures/dupcomposer-config.yml')
     cls.cmds_expected_bkup = \
         {'my_s3_backups': [['duplicity', '--encrypt-key', 'xxxxxx', '--sign-key', 'xxxxxx',
                             '--volsize', '50',
                             '--file-prefix-archive', 'archive_',
                             '--file-prefix-manifest', 'manifest_',
                             '--file-prefix-signature', 'signature_',
                             '/home/shared',
                             's3://s3.sa-east-1.amazonaws.com/my-backup-bucket/home/shared'],
                            ['duplicity', '--encrypt-key', 'xxxxxx', '--sign-key', 'xxxxxx',
                             '--volsize', '50',
                             '--file-prefix-archive', 'archive_',
                             '--file-prefix-manifest', 'manifest_',
                             '--file-prefix-signature', 'signature_',
                             'etc',
                             's3://s3.sa-east-1.amazonaws.com/my-backup-bucket/etc']],
          'my_s3_boto3_backups': [['duplicity', '--encrypt-key', 'xxxxxx', '--sign-key', 'xxxxxx',
                             '--volsize', '50',
                             '--file-prefix-archive', 'archive_',
                             '--file-prefix-manifest', 'manifest_',
                             '--file-prefix-signature', 'signature_',
                             '/home/shared',
                             'boto3+s3://my-backup-bucket.s3.sa-east-1.amazonaws.com/home/shared'],
                            ['duplicity', '--encrypt-key', 'xxxxxx', '--sign-key', 'xxxxxx',
                             '--volsize', '50',
                             '--file-prefix-archive', 'archive_',
                             '--file-prefix-manifest', 'manifest_',
                             '--file-prefix-signature', 'signature_',
                             'etc',
                             'boto3+s3://my-backup-bucket.s3.sa-east-1.amazonaws.com/etc']],
          'my_local_backups': [['duplicity', '--no-encryption', '--volsize', '200',
                                '/var/www/html', 'file:///root/backups/var/www/html'],
                               ['duplicity', '--no-encryption', '--volsize', '200',
                                'home/tommy', 'file://backups/home/tommy']],
          'my_scp_backups': [['duplicity', '--no-encryption', '--volsize', '200',
                              '/home/katy', 'scp://[email protected]//home/katy'],
                             ['duplicity', '--no-encryption', '--volsize', '200',
                              'home/fun', 'scp://[email protected]/home/fun']]}
Esempio n. 7
0
def check_config_change(config_data, config_filename):
    """Prints a message and exits on config change."""
    cache_filename = '.'.join([config_filename, 'cached'])
    if os.path.isfile(cache_filename):
        cached_groups = read_config(cache_filename).get('backup_groups', {})
        current_groups = config_data.get('backup_groups', {})
        changed_groups = []
        # We need the group names in a deterministic order
        # in the output for testing.
        for group_name in sorted(current_groups.keys()):
            if group_name in cached_groups and \
               current_groups[group_name] != cached_groups[group_name]:
                changed_groups.append(group_name)
        # At least one group changed, abort.
        if changed_groups:
            print('The configuration of existing group(s) '
                  '%s have changed! Backup aborted.\n\n'
                  'If you are certain, that no backup sets will '
                  'be impacted unintentionally by this change, '
                  'rerun dupcomp with the \'-f\' flag that skips '
                  'this safeguard step. You might want to consider '
                  'doing a dry run first, to verify how duplicity '
                  'will be run after the change.' % ', '.join(changed_groups))
            exit(1)
Esempio n. 8
0
 def setUpClass(cls):
     cls.config_data = read_config('tests/fixtures/dupcomposer-config.yml')
     cls.prefixes_for_s3 = (cls.config_data['backup_groups']
                            ['my_s3_backups']['backup_file_prefixes'])
Esempio n. 9
0
 def setUpClass(cls):
     cls.config_data = read_config('tests/fixtures/dupcomposer-config.yml')
     cls.config_sources_for_local = (
         cls.config_data['backup_groups']['my_local_backups']['sources'])
     cls.config_provider_local = (cls.config_data['backup_groups']
                                  ['my_local_backups']['backup_provider'])
Esempio n. 10
0
 def setUpClass(cls):
     cls.config_data = read_config('tests/fixtures/dupcomposer-config.yml')
Esempio n. 11
0
def main():
    check_duplicity_version(get_terminal_encoding())
    # default config file to look for
    config_file = 'dupcomposer-config.yml'
    dry_run = False
    skip_config_safeguard = False
    full_backup = False
    # Collecting and parsing options
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'c:dhsf')
    except getopt.GetoptError as err:
        print(err)
        usage()
        sys.exit(1)

    for opt, a in opts:
        # Use specific config file
        if opt == '-c':
            if os.path.isfile(a):
                config_file = a
            else:
                usage()
                raise FileNotFoundError(
                    "Configuration file {} doesn't exist!".format(a))
        # Simply output the duplicity commands, don't execute
        elif opt == '-d':
            dry_run = True
        # Skip config change test
        elif opt == '-s':
            skip_config_safeguard = True
        elif opt == '-f':
            full_backup = True
        elif opt == '-h':
            usage()
            sys.exit(0)

    if not args or args[0] not in ['backup', 'restore']:
        print('backup|restore action is missing from the command!')
        usage()
        sys.exit(1)

    if full_backup and args[0] == 'restore':
        print('-f: force full backup is an invalid option for a restore.')
        usage()
        sys.exit(1)

    config_raw = read_config(config_file)
    # Check if groups requested are valid
    for group in args[1:]:
        if group not in config_raw.get('backup_groups', {}):
            raise ValueError('No group {} in the configuration!'.format(group))
    # Check if any of the existing groups have changed
    if not skip_config_safeguard:
        check_config_change(config_raw, config_file)
    # Setting up the environment
    config = BackupConfig(config_raw)
    runner = BackupRunner(config, args[0], full_backup)

    # Do the actual run
    if dry_run:
        commands = runner.get_cmds_raw(args[1:])
        # Sorting keys for consistent ordering of output (for functional tests).
        for group in sorted(commands):
            print('Generating commands for group {}:\n'.format(group))
            for cmd in commands[group]:
                print(' '.join(cmd))

            print()
    else:
        # True run
        runner.run_cmds(args[1:])
        # Cache current run's config so that we can compare later
        save_config_cache(config_file)
Esempio n. 12
0
 def test_load_goodfile(self):
     config = read_config('tests/fixtures/dupcomposer-config.yml')
     self.assertEqual(config['backup_groups']['my_s3_backups']['volume_size'], 50)