IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 40937


Ignore:
Timestamp:
Oct 11, 2019, 3:49:23 PM (7 years ago)
Author:
fairlamb
Message:

Split atlassian backups out into distinct jira & conf. Testing moved into either backups, or inherited classes

Location:
branches/ipp-259_genericise_backups/tools/backups
Files:
8 added
2 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • branches/ipp-259_genericise_backups/tools/backups/backup.py

    r40932 r40937  
    11import configparser
    22import datetime
     3import os
    34import os.path as path
    45import socket
    56import subprocess
     7from configparser import ConfigParser
    68
    79import backups.utils.config_parse_helper as cfg_help
    810import backups.utils.errors as errs
    911import backups.utils.subprocess_utils as sub_utils
    10 from configparser import ConfigParser
     12from backups.utils.config_parse_helper import ConfigSchema, ConfigSchemaLine
    1113
    1214DEFAULT_CONFIG_FILE = path.join(path.dirname(__file__), 'atlassian_backups.config')
     
    1921
    2022    def __init__(self, config_file=None):
    21         self.config_file = DEFAULT_CONFIG_FILE if config_file is None else config_file
    22         self.load_config(self.config_file)
     23        if config_file is None:
     24            raise errs.ValidationError("ValidationError: Backup class must be given a config")
     25        self.load_config(config_file)
    2326
    2427    def load_config(self, config_class_or_filepath):
     
    3336            config.read(config_class_or_filepath)
    3437
    35         self._read_default_section(config)
     38        self.read_default_section(config)
    3639        if self._has_copy_section(config):
    37             self._read_copy_config_section(config)
     40            self.read_copy_config_section(config)
    3841        if self._has_tar_section(config):
    39             self._read_tar_config_section(config)
     42            self.read_tar_config_section(config)
    4043        if self._has_rsync_section(config):
    41             self._read_rsync_config_section(config)
     44            self.read_rsync_config_section(config)
    4245        if self._has_mysqldump_section(config):
    43             self._read_mysqldump_config_section(config)
     46            self.read_mysqldump_config_section(config)
    4447
    4548    def _has_copy_section(self, config_parser: ConfigParser) -> bool:
     
    6366        return self.run_mysqldump
    6467
    65     DEFAULT_SCHEMA = cfg_help.ConfigSchema('DEFAULT',
    66         [ cfg_help.ConfigSchemaLine('backup_paths', True, list, cfg_help.SpecialSchemaProcessing.commma_separated)
    67         , cfg_help.ConfigSchemaLine('source_machine', True, str)
    68         , cfg_help.ConfigSchemaLine('verbose', False, bool)
    69         ]
    70     )
    71 
    72     def _read_default_section(self, config: ConfigParser):
    73         self.default_dict = cfg_help.parse_config(config, self.DEFAULT_SCHEMA)
     68    DEFAULT_SCHEMA = ConfigSchema('DEFAULT',
     69        [ ConfigSchemaLine('backup_paths', True, list, cfg_help.SpecialSchemaProcessing.commma_separated)
     70        , ConfigSchemaLine('source_machine', True, str)
     71        , ConfigSchemaLine('verbose', False, bool)
     72        , ConfigSchemaLine('make_dirs', False, bool)
     73        ]
     74    )
     75
     76    def read_default_section(self, config: ConfigParser, schema: ConfigSchema=DEFAULT_SCHEMA):
     77        self.default_dict = cfg_help.parse_config(config, schema)
    7478        self.hostname_is_valid()
    75 
    76     COPY_SCHEMA = cfg_help.ConfigSchema('COPY',
    77         [ cfg_help.ConfigSchemaLine('sources', True, list, cfg_help.SpecialSchemaProcessing.commma_separated)
    78         , cfg_help.ConfigSchemaLine('additional_args', False, list, cfg_help.SpecialSchemaProcessing.space_separated)
    79         ]
    80     )
    81 
    82     def _read_copy_config_section(self, config: ConfigParser):
    83         self.copy_dict = cfg_help.parse_config(config, self.COPY_SCHEMA)
    84 
    85     TAR_SCHEMA = cfg_help.ConfigSchema('TAR',
    86         [ cfg_help.ConfigSchemaLine('sources', True, list, cfg_help.SpecialSchemaProcessing.commma_separated)
    87         , cfg_help.ConfigSchemaLine('additional_args', False, list, cfg_help.SpecialSchemaProcessing.space_separated)
    88         , cfg_help.ConfigSchemaLine('target_filename', True, str)
    89         , cfg_help.ConfigSchemaLine('prefix_date', True, bool)
    90         ]
    91     )
    92 
    93     def _read_tar_config_section(self, config: ConfigParser):
    94         self.tar_dict = cfg_help.parse_config(config, self.TAR_SCHEMA)
    95 
    96     RSYNC_SCHEMA = cfg_help.ConfigSchema('RSYNC',
    97         [ cfg_help.ConfigSchemaLine('sources', True, list, cfg_help.SpecialSchemaProcessing.commma_separated)
    98         , cfg_help.ConfigSchemaLine('additional_args', False, list, cfg_help.SpecialSchemaProcessing.space_separated)
    99         ]
    100     )
    101 
    102     def _read_rsync_config_section(self, config: ConfigParser):
    103         self.rsync_dict = cfg_help.parse_config(config, self.RSYNC_SCHEMA)
    104 
    105     MYSQLDUMP_SCHEMA = cfg_help.ConfigSchema('MYSQLDUMP',
    106         [ cfg_help.ConfigSchemaLine('user', True, str)
    107         , cfg_help.ConfigSchemaLine('password', True, str)
    108         , cfg_help.ConfigSchemaLine('db_name', True, str)
    109         , cfg_help.ConfigSchemaLine('additional_args', False, list, cfg_help.SpecialSchemaProcessing.space_separated)
    110         , cfg_help.ConfigSchemaLine('target_filename', True, str)
    111         , cfg_help.ConfigSchemaLine('prefix_date', True, bool)
    112         ]
    113     )
    114 
    115     def _read_mysqldump_config_section(self, config: ConfigParser):
    116         self.mysqldump_dict = cfg_help.parse_config(config, self.MYSQLDUMP_SCHEMA)
     79        self.maybe_make_backup_dirs()
     80
     81    COPY_SCHEMA = ConfigSchema('COPY',
     82        [ ConfigSchemaLine('sources', True, list, cfg_help.SpecialSchemaProcessing.commma_separated)
     83        , ConfigSchemaLine('additional_args', False, list, cfg_help.SpecialSchemaProcessing.space_separated)
     84        ]
     85    )
     86
     87    def read_copy_config_section(self, config: ConfigParser, schema: ConfigSchema=COPY_SCHEMA):
     88        self.copy_dict = cfg_help.parse_config(config, schema)
     89
     90    TAR_SCHEMA = ConfigSchema('TAR',
     91        [ ConfigSchemaLine('sources', True, list, cfg_help.SpecialSchemaProcessing.commma_separated)
     92        , ConfigSchemaLine('additional_args', False, list, cfg_help.SpecialSchemaProcessing.space_separated)
     93        , ConfigSchemaLine('target_filename', True, str)
     94        , ConfigSchemaLine('prefix_date', True, bool)
     95        ]
     96    )
     97
     98    def read_tar_config_section(self, config: ConfigParser, schema: ConfigSchema=TAR_SCHEMA):
     99        self.tar_dict = cfg_help.parse_config(config, schema)
     100
     101    RSYNC_SCHEMA = ConfigSchema('RSYNC',
     102        [ ConfigSchemaLine('sources', True, list, cfg_help.SpecialSchemaProcessing.commma_separated)
     103        , ConfigSchemaLine('additional_args', False, list, cfg_help.SpecialSchemaProcessing.space_separated)
     104        ]
     105    )
     106
     107    def read_rsync_config_section(self, config: ConfigParser, schema: ConfigSchema=RSYNC_SCHEMA):
     108        self.rsync_dict = cfg_help.parse_config(config, schema)
     109
     110    MYSQLDUMP_SCHEMA = ConfigSchema('MYSQLDUMP',
     111        [ ConfigSchemaLine('user', True, str)
     112        , ConfigSchemaLine('password', True, str)
     113        , ConfigSchemaLine('db_name', True, str)
     114        , ConfigSchemaLine('additional_args', False, list, cfg_help.SpecialSchemaProcessing.space_separated)
     115        , ConfigSchemaLine('target_filename', True, str)
     116        , ConfigSchemaLine('prefix_date', True, bool)
     117        ]
     118    )
     119
     120    def read_mysqldump_config_section(self, config: ConfigParser, schema: ConfigSchema=MYSQLDUMP_SCHEMA):
     121        self.mysqldump_dict = cfg_help.parse_config(config, schema)
    117122
    118123    def hostname_is_valid(self) -> bool:
     
    122127        actual_hostname = socket.gethostname()
    123128        return actual_hostname == self.default_dict['source_machine']
     129
     130    def target_backup_paths_ok(self, raise_error=False):
     131        for bp in self.default_dict['backup_paths']:
     132            if not path.exists(bp):
     133                if raise_error:
     134                    raise errs.ValidationError(f"ValidationError: target path does not exist: {bp}")
     135                return False
     136        return True
     137
     138    def maybe_make_backup_dirs(self):
     139        if self.default_dict is None or 'make_dirs' not in self.default_dict.keys():
     140            return
     141        if self.default_dict['make_dirs']:
     142            for backup_path in self.default_dict['backup_paths']:
     143                if not os.path.exists(backup_path):
     144                    os.makedirs(backup_path)
    124145
    125146    def run_backup(self):
     
    132153        if self.run_copy is None or False:
    133154            return 0
     155        self.target_backup_paths_ok(raise_error=True)
    134156
    135157        for bp in self.default_dict['backup_paths']:
    136             if not path.exists(bp):
    137                     raise errs.ValidationError(f"ValidationError: target path does not exist: {bp}")
     158            # if not path.exists(bp):
     159            #         raise errs.ValidationError(f"ValidationError: target path does not exist: {bp}")
    138160
    139161            for s in self.copy_dict['sources']:
     
    143165                    args = [s, bp]
    144166                    if 'additional_args' in self.copy_dict.keys():
    145                         print("hiya")
    146167                        args = args + self.copy_dict['additional_args']
    147168                    sub_utils.cp_wrapper(args)
     
    168189
    169190        try:
    170             print(all_args)
    171191            sub_utils.tar_wrapper(all_args)
    172192            sub_utils.chmod_wrapper(['774', filename])
     
    184204            return 0
    185205
     206        self.target_backup_paths_ok(raise_error=True)
    186207        backup_paths = self.default_dict['backup_paths']
    187208        for bp in backup_paths:
    188             if not path.exists(bp):
    189                 raise errs.ValidationError(f"ValidationError: target path does not exist: {bp}")
     209            # if not path.exists(bp):
     210            #     raise errs.ValidationError(f"ValidationError: target path does not exist: {bp}")
    190211
    191212            for s in self.rsync_dict['sources']:
     
    195216                    args = [s, bp]
    196217                    if 'additional_args' in self.rsync_dict.keys():
    197                         print("hiya")
    198218                        args = args + self.rsync_dict['additional_args']
    199                         print(args)
    200219                    sub_utils.local_rsync_wrapper(args)
    201220                except errs.SubprocessError as e:
     
    240259        for d in range(1, len(backup_paths)):
    241260            sub_utils.cp_wrapper([dump_filename, backup_paths[d]])
    242 
    243 
    244 def get_date(custom_date=None, custom_format="%Y-%b-%d"):
     261        return 0
     262
     263
     264def get_date(custom_date=None, custom_format="%Y_%m_%d"):
    245265        # Format is currently: 2019-10-08
    246266        if custom_date is not None:
  • branches/ipp-259_genericise_backups/tools/backups/backup_test.py

    r40932 r40937  
    2727    source_machine = socket.gethostname()
    2828    config['DEFAULT'] = \
    29     {
    30         'backup_paths'   : backup_paths,
    31         'source_machine' : source_machine,
    32         'verbose'        : verbose,
    33     }
     29        { 'backup_paths'   : backup_paths
     30        , 'source_machine' : source_machine
     31        , 'verbose'        : verbose
     32        }
    3433    return config
    3534
     
    107106            Backup(config_file=config)
    108107
    109         with pytest.raises(errs.ConfigError):
     108        with pytest.raises(errs.ValidationError):
    110109            Backup(config_file=None)
    111110
     
    136135        backy.default_dict['source_machine'] = actual_hostname
    137136        assert backy.hostname_is_valid() is True
     137
     138
     139class TestFilepathVerifications(object):
     140
     141    def test_default_target_paths_do_not_exist_in_testing(self):
     142        backy = Backup(config_file=TEST_DEFAULT_CONFIG_FILE)
     143        assert backy.target_backup_paths_ok() is False
     144
     145    def test_raising_an_error_if_a_backup_path_does_not_exist(self):
     146        with pytest.raises(errs.ValidationError) as e:
     147            backy = Backup(config_file=TEST_DEFAULT_CONFIG_FILE)
     148            backy.target_backup_paths_ok(raise_error=True)
     149        assert "ValidationError: target path does not exist" in str(e)
     150
     151    def test_an_incorrect_path_then_correct_path(self, tmpdir):
     152        backy = Backup(config_file=TEST_DEFAULT_CONFIG_FILE)
     153
     154        backy.default_dict['backup_paths'] = ["/not/real/path"]
     155        assert backy.target_backup_paths_ok() is False
     156
     157        backy.default_dict['backup_paths'] = [tmpdir]
     158        assert backy.target_backup_paths_ok() is True
     159
     160    def test_backup_paths_created_if_make_dirs_given(self, tmpdir):
     161        config = ConfigParser()
     162        config['DEFAULT'] = \
     163            { 'backup_paths'   : f"{tmpdir}/bck1/bobby/backup, {tmpdir}/bck2"
     164            , 'source_machine' : 'rocket'
     165            , 'verbose'        : 'True'
     166            }
     167        bck1_path   = os.path.join(tmpdir, 'bck1')
     168        bck1b_path  = os.path.join(tmpdir, 'bck1/bobby')
     169        bck1bb_path = os.path.join(tmpdir, 'bck1/bobby/backup')
     170        bck2_path   = os.path.join(tmpdir, 'bck2')
     171        assert not os.path.exists(bck1_path)
     172        assert not os.path.exists(bck1b_path)
     173        assert not os.path.exists(bck1bb_path)
     174        assert not os.path.exists(bck2_path)
     175        # backup dirs not created automatically
     176        Backup(config)
     177        assert not os.path.exists(bck1_path)
     178        assert not os.path.exists(bck1b_path)
     179        assert not os.path.exists(bck1bb_path)
     180        assert not os.path.exists(bck2_path)
     181
     182        # make_dirs included in config - when loaded dirs created.
     183        config['DEFAULT'] = \
     184            { 'backup_paths'   : f"{tmpdir}/bck1/bobby/backup, {tmpdir}/bck2"
     185            , 'source_machine' : 'rocket'
     186            , 'verbose'        : 'True'
     187            , 'make_dirs'      : 'True'
     188            }
     189        backy = Backup(config)
     190        assert backy.default_dict['make_dirs'] is True
     191        assert os.path.exists(bck1_path)
     192        assert os.path.exists(bck1b_path)
     193        assert os.path.exists(bck1bb_path)
     194        assert os.path.exists(bck2_path)
    138195
    139196
     
    265322        assert not os.path.exists(expected_tar1)
    266323        backy._run_tar()
    267         print(expected_tar1)
    268324        assert os.path.exists(expected_tar1)
    269325
     
    422478"""
    423479
    424     dumper_password = "not_a_real_password"
    425 
    426480    def test_mysql_dump_is_ok(self, tmpdir):
    427481        config = make_default_config(tmpdir, ['bck1', 'bck2'])
     
    442496        assert not os.path.exists(expected_dump1)
    443497        assert not os.path.exists(expected_dump2)
    444         backy._run_mysqldump()
     498        result = backy._run_mysqldump()
    445499        assert os.path.exists(expected_dump1)
    446500        assert os.path.exists(expected_dump2)
     501
     502        assert result == 0
    447503
    448504    def test_mysql_dump_fails_with_incorrect_password(self, tmpdir):
  • branches/ipp-259_genericise_backups/tools/backups/utils/config_parse_helper.py

    r40920 r40937  
    8686    for csl_key in schema.options:
    8787        csl = schema.get_schema_line(csl_key)
    88         print(csl)
    8988
    9089        if config.has_option(section, csl_key):
Note: See TracChangeset for help on using the changeset viewer.