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'])
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': '******' }
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 = {}
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': '******' }
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] }
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']]}
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)
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'])
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'])
def setUpClass(cls): cls.config_data = read_config('tests/fixtures/dupcomposer-config.yml')
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)
def test_load_goodfile(self): config = read_config('tests/fixtures/dupcomposer-config.yml') self.assertEqual(config['backup_groups']['my_s3_backups']['volume_size'], 50)