~jcsackett/charmworld/bac-tag-constraints

« back to all changes in this revision

Viewing changes to charmworld/migrations/versions/tests/test_migrations.py

  • Committer: Tarmac
  • Author(s): Brad Crittenden
  • Date: 2014-04-22 19:06:44 UTC
  • mfrom: (504.1.2 026-3)
  • Revision ID: tarmac-20140422190644-nep5wth304pk36p8
Fix migration wrt invalid constraints.

The migration 026 for rewriting contraints to be space-separated worked for
staging.  When run on production it had errors due to some of the bundles on
production being older than the more restrictive bundle proofing
requirements.  Those bundles were in essence grandfathered in and never
subject to the stricter rules.  At least one bundle had an obsolete 'cpu'
constraint and that caused the migration to fail since it was not checking for
the thrown ValueError in this situation.

The migration now checks for ValueError and will remove the affected bundle
from the target database and proceed.

The functions are now noted to throw ValueError.

Test was added for this situation and logging checked.

https://codereview.appspot.com/90420043/

R=jcsackett.

Approved by Juju Gui Bot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
from charmworld.migrations import migrate
13
13
from charmworld.migrations.migrate import Versions
14
14
 
15
 
from mock import patch
 
15
import logging
 
16
import mock
16
17
 
17
18
 
18
19
class MigrationTestBase(MongoTestBase):
20
21
    def setUp(self):
21
22
        super(MigrationTestBase, self).setUp()
22
23
        self.versions = Versions(migrate.get_migration_path())
23
 
        self.use_context(patch.object(migrate, 'configure_logging'))
 
24
        self.use_context(mock.patch.object(migrate, 'configure_logging'))
24
25
 
25
26
 
26
27
class TestExodus026(MigrationTestBase):
31
32
    def setUp(self):
32
33
        super(TestExodus026, self).setUp()
33
34
        self.use_index_client()
 
35
        self.source = CharmSource.from_request(self)
 
36
        self.source_db = self.source.collection.database
 
37
        self.exodus_update = self.versions.get_exodus(
 
38
            self.exodus)
 
39
        self.target = self.versions.get_pending_source(
 
40
            self.source, self.version)
 
41
        self.target_db = self.target.collection.database
34
42
 
35
43
    # Test converting service constraints to space-separated.
36
44
    def test_converts_constraints(self):
37
 
        source = CharmSource.from_request(self)
38
 
        source_db = source.collection.database
39
 
        exodus_update = self.versions.get_exodus(
40
 
            self.exodus)
41
 
        target = self.versions.get_pending_source(source, self.version)
42
 
        target_db = target.collection.database
43
45
        services = dict(
44
46
            svc1=dict(constraints='cpu-cores=4,mem=2G,arch=i686'),
45
47
            svc2=dict(constraints='cpu-cores=44 arch=i386 mem=9G'),
46
48
        )
47
 
        self.assertEqual(0, source_db.bundles.count())
48
 
        self.assertEqual(0, target_db.bundles.count())
49
 
        _, bundle_data = factory.make_bundle(source_db, services=services)
 
49
        self.assertEqual(0, self.source_db.bundles.count())
 
50
        self.assertEqual(0, self.target_db.bundles.count())
 
51
        _, bundle_data = factory.make_bundle(
 
52
            self.source_db, services=services)
50
53
        # Add in 'inherits' property to exercise its deletion.
51
54
        bundle_data['data']['inherits'] = 'super-charm'
52
 
        source_db.bundles.save(bundle_data)
53
 
        self.assertEqual(1, source_db.bundles.count())
54
 
        self.assertEqual(1, target_db.bundles.count())
 
55
        self.source_db.bundles.save(bundle_data)
 
56
        self.assertEqual(1, self.source_db.bundles.count())
 
57
        self.assertEqual(1, self.target_db.bundles.count())
55
58
 
56
59
        # Run the exodus.
57
 
        exodus_update(source, target, self.version)
 
60
        self.exodus_update(self.source, self.target, self.version)
58
61
        # Ensure there is still just the one bundle.
59
 
        self.assertEqual(1, target_db.bundles.count())
60
 
        converted = target_db.bundles.find_one()
 
62
        self.assertEqual(1, self.target_db.bundles.count())
 
63
        converted = self.target_db.bundles.find_one()
61
64
        services = converted['data']['services']
62
65
        # Constraints are now space-separated and sorted.
63
66
        self.assertEqual(services['svc1']['constraints'],
65
68
        self.assertEqual(services['svc2']['constraints'],
66
69
                         'arch=i386 cpu-cores=44 mem=9G')
67
70
 
 
71
    def test_skips_invalid_constraints(self):
 
72
        services = dict(
 
73
            # 'cpu' is an obsolete constraint name.
 
74
            svc1=dict(constraints='cpu=4,mem=2G,arch=i686'),
 
75
        )
 
76
        self.assertEqual(0, self.source_db.bundles.count())
 
77
        self.assertEqual(0, self.target_db.bundles.count())
 
78
        _, bundle_data = factory.make_bundle(
 
79
            self.source_db, services=services)
 
80
        self.source_db.bundles.save(bundle_data)
 
81
        self.assertEqual(1, self.source_db.bundles.count())
 
82
        self.assertEqual(1, self.target_db.bundles.count())
 
83
 
 
84
        # Run the exodus.
 
85
        log = logging.getLogger('charm.exodus026')
 
86
        with mock.patch.object(log, 'warning') as mock_warn:
 
87
            self.exodus_update(self.source, self.target, self.version)
 
88
        # There are now no bundles, as the invalid one was removed from the
 
89
        # target database.
 
90
        self.assertEqual(0, self.target_db.bundles.count())
 
91
        expected_warnings = [
 
92
            'Bundle has invalid constraint.  Skipping {}'.format(
 
93
                bundle_data['_id']),
 
94
        ]
 
95
        mock_warn.assert_has_calls(
 
96
            [mock.call(msg) for msg in expected_warnings])
 
97
 
68
98
 
69
99
class TestExodusRestrictions(MigrationTestBase):
70
100