Projet

Général

Profil

0003-management-passer-convert-to-sql-en-commande-de-mana.patch

Christophe Siraut, 15 juin 2018 16:41

Télécharger (8,47 ko)

Voir les différences:

Subject: [PATCH 3/3] management: passer convert-to-sql en commande de
 management (#20410)

 tests/test_convert_to_sql.py                  |  59 ++++++++++++-
 wcs/ctl/management/commands/__init__.py       |  23 +++++
 wcs/ctl/management/commands/convert_to_sql.py | 116 ++++++++++++++++++++++++++
 3 files changed, 197 insertions(+), 1 deletion(-)
 create mode 100644 wcs/ctl/management/commands/convert_to_sql.py
tests/test_convert_to_sql.py
1
import sys
1 2
import pytest
2 3
from django.core.management import get_commands
3 4
from django.core.management import call_command
5
from django.core.management.base import CommandError
6
from wcs.ctl.management.commands.convert_to_sql import Command
7
from utilities import clean_temporary_pub
8
from utilities import create_temporary_pub
9
from utilities import force_connections_close
10
import json
11

  
12
if sys.version_info[0] > 2:
13
    from unittest.mock import MagicMock
14
else:
15
    from mock import MagicMock
16

  
17

  
18

  
19
def pytest_generate_tests(metafunc):
20
    if 'cmd' in metafunc.fixturenames:
21
        metafunc.parametrize('cmd', ['pickle', 'sql'], indirect=True)
22

  
23

  
24
def teardown_module(module):
25
    force_connections_close()
26
    clean_temporary_pub()
27

  
28

  
29
@pytest.fixture
30
def cmd(request):
31
    c = Command()
32
    c.pub = create_temporary_pub(sql_mode=(request.param == 'sql'))
33
    c.get_publisher = MagicMock(return_value=c.pub)
34
    if request.param != 'sql':
35
        new_database_pub = create_temporary_pub(sql_mode=True)
36
        cfg = '''{"postgresql": {
37
            "database-template-name": "wcs_%%s",
38
            "user": "%(user)s"}}''' % new_database_pub.cfg['postgresql']
39
        c.get_default_cfg = MagicMock(return_value=json.loads(cfg))
40
    return c
4 41

  
5 42

  
6 43
def test_command_exists():
7
   assert 'convert_to_sql' in get_commands()
44
    assert 'convert_to_sql' in get_commands()
45

  
46

  
47
def test_unknown_publisher_fails():
48
    with pytest.raises(CommandError) as excinfo:
49
        call_command('convert_to_sql', '-d', 'unknown.net')
50
    assert excinfo.value.message == 'unknown tenant'
51

  
52

  
53
def test_already_migrated_fails(cmd):
54
    if cmd.pub.is_using_postgresql():
55
        with pytest.raises(CommandError) as excinfo:
56
            cmd.execute(domain='example.net', skeleton='publik')
57
        assert excinfo.value.message == 'tenant already using postgresql'
58

  
59

  
60
def test_migration(cmd):
61
    if not cmd.pub.is_using_postgresql():
62
        assert 'postgresql' not in cmd.pub.cfg
63
        cmd.execute(domain='example.net', skeleton='publik')
64
        assert 'postgresql' in cmd.pub.cfg
wcs/ctl/management/commands/__init__.py
1
import os
2
from django.core.management.base import BaseCommand, CommandError
3
from qommon.publisher import get_publisher_class
4

  
5

  
6
class WcsTenantCommand(BaseCommand):
7

  
8
    def add_arguments(self, parser):
9
        parser.add_argument('-d', '--domain', metavar='DOMAIN', required=True)
10
        super(WcsTenantCommand, self).add_arguments(parser)
11

  
12
    def execute(self, *args, **kwargs):
13
        self.publisher = self.get_publisher(kwargs['domain'])
14
        super(WcsTenantCommand, self).execute(*args, **kwargs)
15

  
16
    def get_publisher(self, domain):
17
        publisher_class = get_publisher_class()
18
        publisher = publisher_class.create_publisher()
19
        if domain not in publisher.get_tenants():
20
            raise CommandError('unknown tenant')
21
        publisher.app_dir = os.path.join(publisher.app_dir, domain)
22
        publisher.set_config()
23
        return publisher
wcs/ctl/management/commands/convert_to_sql.py
1
import os
2
import sys
3
from django.core.management.base import CommandError
4
from wcs import publisher
5
# from wcs.ctl.convertsql import CmdConvertToSql
6
from wcs import sql
7
from wcs.ctl.management.commands import WcsTenantCommand
8
from wcs.formdef import FormDef
9
from wcs.users import User
10
import traceback
11

  
12

  
13
class Command(WcsTenantCommand):
14

  
15
    def add_arguments(self, parser):
16
        parser.add_argument('-s', '--skeleton', default='publik')
17
        super(Command, self).add_arguments(parser)
18

  
19
    def handle(self, *args, **options):
20
        if self.publisher.is_using_postgresql():
21
            raise CommandError('tenant already using postgresql')
22

  
23
        self.publisher.cfg['postgresql'] = self.get_postgresql_cfg(
24
            options['domain'], options['skeleton'])
25

  
26
        self.publisher.cleanup()
27

  
28
    def get_postgresql_cfg(self, domain, skeleton):
29
        cfg = self.get_default_cfg(skeleton)
30
        pg_cfg = cfg['postgresql']
31
        pg_cfg['dbname'] = pg_cfg['database-template-name'] % domain
32
        del pg_cfg['database-template-name']
33
        return pg_cfg
34

  
35
    def get_default_cfg(self, skeleton):
36
        tpub = publisher.WcsPublisher.create_publisher(
37
                   register_tld_names=False)
38
        skeleton_fp = os.path.join(self.publisher.app_dir, 'skeletons',
39
                                   '{}.zip'.format(skeleton))
40
        if not(os.path.isfile(skeleton_fp)):
41
            raise CommandError('skeleton not found')
42
        tpub.import_zip(skeleton_fp)
43
        return tpub.cfg
44

  
45
    def convert_to_sql(self):
46
        sql.get_connection_and_cursor(new=True)
47

  
48
        errors = []
49

  
50
        print('converting users')
51
        sql.do_user_table()
52
        count = User.count()
53
        for i, user_id in enumerate(User.keys()):
54
            user = User.get(user_id)
55
            user.__class__ = sql.SqlUser
56
            try:
57
                user.store()
58
            except AssertionError:
59
                errors.append((user, traceback.format_exc()))
60
            # update_progress(100*i/count)
61
        sql.SqlUser.fix_sequences()
62

  
63
        if errors:
64
            error_log = open('error_user.log', 'w')
65
            for user, trace in errors:
66
                error_log.write('user_id {}'.format(user.id))
67
                error_log.write(trace)
68
                error_log.write('-'*80)
69
            error_log.close()
70
            print('There were some errors, see error_user.log for details.')
71

  
72
        errors = []
73
        for formdef in FormDef.select():
74
            print('converting %s' % formdef.name)
75
            sql.do_formdef_tables(formdef, rebuild_views=True,
76
                    rebuild_global_views=True)
77
            data_class = formdef.data_class(mode='files')
78
            count = data_class.count()
79

  
80
            # load all objects a first time, to allow the migrate() code to be
81
            # run and the eventual changes properly saved.
82
            for id in data_class.keys():
83
                formdata = data_class.get(id)
84
            delattr(sys.modules['formdef'], formdef.url_name.title())
85

  
86
            # once this is done, reload and store everything in postgresql
87
            sql_data_class = formdef.data_class(mode='sql')
88
            for i, id in enumerate(data_class.keys()):
89
                formdata = data_class.get(id)
90
                formdata._formdef = formdef
91
                formdata._evolution = formdata.evolution
92
                formdata.__class__ = sql_data_class
93
                try:
94
                    formdata.store()
95
                except AssertionError:
96
                    errors.append((formdata, traceback.format_exc()))
97
                # update_progress(100*i/count)
98
            sql_data_class.fix_sequences()
99

  
100
        sql.do_tracking_code_table()
101
        sql.do_session_table()
102
        sql.do_meta_table()
103

  
104
        if errors:
105
            error_log = open('error_formdata.log', 'w')
106
            for formdata, trace in errors:
107
                error_log.write('{} {}'.format(formdata.fromdef, formdata.id))
108
                error_log.write(trace)
109
                error_log.write('-'*80)
110
            error_log.close()
111
            print('There were some errors, see error_formdata.log.')
112

  
113
        if not self.publisher.has_site_option('postgresql'):
114
            print('You still have to edit your site-options.cfg')
115

  
116
        self.publisher.write_cfg()
0
-