Code review comment for lp:~salgado/launchpad/remove-auth-store

Revision history for this message
Guilherme Salgado (salgado) wrote :

On Thu, 2010-04-01 at 15:12 +0000, Stuart Bishop wrote:
> Review: Approve
> On Wed, Mar 31, 2010 at 2:00 AM, Guilherme Salgado
> <email address hidden> wrote:
>
> > Remove the auth store, together with c-i-p.
> >
> > Had to grant some extra DB permissions on security.cfg because some
> > things that used to be done using the launchpad_auth user (the one
> > always used for the auth store, regardless of what was given to
> > initZopeless) are now done using whichever user is used by the
> > script/test.
>
> Yay. This is more than I expected.

More than I expected too. :/

And to make things worse, there are a couple extra revisions that
weren't in the diff you reviewed (I'm assuming you reviewed the diff
that was sent out when the m-p was created):

http://bazaar.launchpad.net/~salgado/launchpad/remove-auth-store/revision/10563
http://bazaar.launchpad.net/~salgado/launchpad/remove-auth-store/revision/10564

They're trivial, though.

>
>
>
> > === modified file 'lib/canonical/launchpad/database/tests/test_oauth.py'
> > --- lib/canonical/launchpad/database/tests/test_oauth.py 2009-06-25 05:30:52 +0000
> > +++ lib/canonical/launchpad/database/tests/test_oauth.py 2010-03-30 19:00:44 +0000
> > @@ -22,7 +22,7 @@
> > """Base tests for the OAuth database classes."""
> > layer = DatabaseFunctionalLayer
> >
> > - def test__get_store_should_return_the_auth_master_store(self):
> > + def test__get_store_should_return_the_main_master_store(self):
> > """We want all OAuth classes to use the master store.
> > Otherwise, the OAuth exchanges will fail because the authorize
> > screen won't probably find the new request token on the slave store.
>
> Does this test serve any purpose any more? Maybe remove it entirely.
>

AIUI, it's necessary because we want to make sure that we use the master
store (by default) when dealing with OAuth-related objects. (The name
of the test method was actually wrong; this is not related to the other
changes on this branch)

>
> > === modified file 'lib/canonical/launchpad/webapp/adapter.py'
> > try:
> > + # XXX: Salgado, 2010-03-22: We can get rid of the realm now that
> > + # the auth DB is gone, but I'm not doing it in this branch to keep
> > + # the diff simple.
> > config_section, realm, flavor = self._uri.database.split('-')
> > except ValueError:
> > raise AssertionError(
> > 'Connection uri %s does not match section-realm-flavor format'
> > % repr(self._uri.database))
>
> I don't think this XXX is warranted. We may well have more realms in
> the future, for example if we move translations or codehosting to
> their own database for scalability reasons.

Fair enough; I thought we'd remove that because I had never heard of
these plans.

>
> > === modified file 'lib/canonical/launchpad/webapp/ftests/test_adapter_permissions.txt'
> > -
> > -A MASTER_FLAVOR Store does not allow writes to tables outside of that
> > -Store's replication set.
> > -
> > - >>> t = transaction.begin()
> > - >>> person = main_master.find(Person, name='no-priv').one()
> > - >>> account = person.account
> > - >>> account.displayname = "Ben Dover"
> > - >>> main_master.flush()
> > - Traceback (most recent call last):
> > - ...
> > - ProgrammingError: permission denied for relation account
> > - >>> transaction.abort()
> > -
> > - >>> t = transaction.begin()
> > - >>> auth_master = getUtility(IStoreSelector).get(AUTH_STORE, MASTER_FLAVOR)
> > - >>> person = auth_master.find(Person, name='no-priv').one()
> > - >>> account = person.account
> > - >>> account.displayname = "Ben Dover"
> > - >>> auth_master.flush()
> > - >>> transaction.abort()
>
> But this crap can certainly go. If we split the database in the
> future, there will be no crossover. What I've learned from the
> authdb/lpmain split is that the split needs to be clean, or we end up
> with confusing code (is my email address from the authdb Store or the
> lpmain Store) and a complicated and tricky to maintain replication
> setup. The underlying approach mapping the database class to a Storm
> store is a suitable approach to the sort of sharding that Launchpad
> will need one day.

At this point I can't even remember why we had EmailAddress (& co) on
both databases?

>
>
>
> > + # XXX: 2010-03-24, Guilherme Salgado: The 'name' argument will always be
> > + # MAIN_STORE here, so it can be removed. Not doing it now as this branch
> > + # will be CPed into production.
> > def getStore(name, flavor):
> > """Retrieve a Store.
>
> I think this XXX can go do. I'd rather not re implement this next year :)
>
>
> > @@ -843,6 +843,9 @@
> > def get_current():
> > """Return the currently installed `IDatabasePolicy`."""
> >
> > + # XXX: 2010-03-24, Guilherme Salgado: The 'name' argument will always be
> > + # MAIN_STORE here, so it can be removed. Not doing it now as this branch
> > + # will be CPed into production.
> > def get(name, flavor):
> > """Retrieve a Storm Store.
>
> And here.

Sure, removed both.

>
>
> > === modified file 'lib/canonical/launchpad/webapp/tests/test_dbpolicy.py'
> > --- lib/canonical/launchpad/webapp/tests/test_dbpolicy.py 2010-02-24 23:18:40 +0000
> > +++ lib/canonical/launchpad/webapp/tests/test_dbpolicy.py 2010-03-30 19:00:44 +0000
> > @@ -25,7 +25,7 @@
> > ReadOnlyLaunchpadDatabasePolicy, SlaveDatabasePolicy,
> > SlaveOnlyDatabasePolicy)
> > from canonical.launchpad.webapp.interfaces import (
> > - ALL_STORES, AUTH_STORE, DEFAULT_FLAVOR, DisallowedStore, IDatabasePolicy,
> > + DEFAULT_FLAVOR, DisallowedStore, IDatabasePolicy,
> > IStoreSelector, MAIN_STORE, MASTER_FLAVOR, ReadOnlyModeDisallowedStore,
> > SLAVE_FLAVOR)
>
> I'm tempted to say revert the changes in this file and put back
> ALL_STORES, which would be a list of length one. It will also reduce a
> lot off diff lines in this CP scary branch :)

Sounds good to me, but I'm sure it's still scary for a CP branch.

>
>
>
> > def test_dbusers(self):
> > store_selector = getUtility(IStoreSelector)
> > main_store = store_selector.get(MAIN_STORE, DEFAULT_FLAVOR)
> > self.failUnlessEqual(self.getDBUser(main_store), 'launchpad_main')
> >
> > - auth_store = store_selector.get(AUTH_STORE, DEFAULT_FLAVOR)
> > - self.failUnlessEqual(self.getDBUser(auth_store), 'launchpad_auth')
>
> Well... not all the changes. Explicit references to AUTH_STORE need to
> go, but the ALL_STORES loops seem fine.

The two lines above were actually the only removals that I kept.

> Surprisingly few comments for a large diff. Thanks :)

Thank you for the quick review! Attached is the incremental diff.

--
Guilherme Salgado <email address hidden>

1=== modified file 'lib/canonical/launchpad/webapp/adapter.py'
2--- lib/canonical/launchpad/webapp/adapter.py 2010-03-30 17:25:52 +0000
3+++ lib/canonical/launchpad/webapp/adapter.py 2010-04-01 15:26:28 +0000
4@@ -349,9 +349,6 @@
5 raise StormAccessFromMainThread()
6
7 try:
8- # XXX: Salgado, 2010-03-22: We can get rid of the realm now that
9- # the auth DB is gone, but I'm not doing it in this branch to keep
10- # the diff simple.
11 config_section, realm, flavor = self._uri.database.split('-')
12 except ValueError:
13 raise AssertionError(
14
15=== modified file 'lib/canonical/launchpad/webapp/interfaces.py'
16--- lib/canonical/launchpad/webapp/interfaces.py 2010-03-30 17:25:52 +0000
17+++ lib/canonical/launchpad/webapp/interfaces.py 2010-04-01 15:37:19 +0000
18@@ -745,6 +745,7 @@
19 #
20
21 MAIN_STORE = 'main' # The main database.
22+ALL_STORES = frozenset([MAIN_STORE])
23
24 DEFAULT_FLAVOR = 'default' # Default flavor for current state.
25 MASTER_FLAVOR = 'master' # The master database.
26@@ -771,9 +772,6 @@
27 utility.
28 """
29
30- # XXX: 2010-03-24, Guilherme Salgado: The 'name' argument will always be
31- # MAIN_STORE here, so it can be removed. Not doing it now as this branch
32- # will be CPed into production.
33 def getStore(name, flavor):
34 """Retrieve a Store.
35
36@@ -843,9 +841,6 @@
37 def get_current():
38 """Return the currently installed `IDatabasePolicy`."""
39
40- # XXX: 2010-03-24, Guilherme Salgado: The 'name' argument will always be
41- # MAIN_STORE here, so it can be removed. Not doing it now as this branch
42- # will be CPed into production.
43 def get(name, flavor):
44 """Retrieve a Storm Store.
45
46
47=== modified file 'lib/canonical/launchpad/webapp/tests/test_dbpolicy.py'
48--- lib/canonical/launchpad/webapp/tests/test_dbpolicy.py 2010-03-24 15:22:26 +0000
49+++ lib/canonical/launchpad/webapp/tests/test_dbpolicy.py 2010-04-01 15:39:56 +0000
50@@ -25,7 +25,7 @@
51 ReadOnlyLaunchpadDatabasePolicy, SlaveDatabasePolicy,
52 SlaveOnlyDatabasePolicy)
53 from canonical.launchpad.webapp.interfaces import (
54- DEFAULT_FLAVOR, DisallowedStore, IDatabasePolicy,
55+ ALL_STORES, DEFAULT_FLAVOR, DisallowedStore, IDatabasePolicy,
56 IStoreSelector, MAIN_STORE, MASTER_FLAVOR, ReadOnlyModeDisallowedStore,
57 SLAVE_FLAVOR)
58 from canonical.launchpad.webapp.servers import LaunchpadTestRequest
59@@ -37,9 +37,10 @@
60 layer = DatabaseFunctionalLayer
61
62 def test_defaults(self):
63- self.assertProvides(
64- getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR),
65- IMasterStore)
66+ for store in ALL_STORES:
67+ self.assertProvides(
68+ getUtility(IStoreSelector).get(store, DEFAULT_FLAVOR),
69+ IMasterStore)
70
71 def test_dbusers(self):
72 store_selector = getUtility(IStoreSelector)
73@@ -79,14 +80,16 @@
74 super(SlaveDatabasePolicyTestCase, self).setUp()
75
76 def test_defaults(self):
77- self.assertProvides(
78- getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR),
79- ISlaveStore)
80+ for store in ALL_STORES:
81+ self.assertProvides(
82+ getUtility(IStoreSelector).get(store, DEFAULT_FLAVOR),
83+ ISlaveStore)
84
85 def test_master_allowed(self):
86- self.assertProvides(
87- getUtility(IStoreSelector).get(MAIN_STORE, MASTER_FLAVOR),
88- IMasterStore)
89+ for store in ALL_STORES:
90+ self.assertProvides(
91+ getUtility(IStoreSelector).get(store, MASTER_FLAVOR),
92+ IMasterStore)
93
94
95 class SlaveOnlyDatabasePolicyTestCase(SlaveDatabasePolicyTestCase):
96@@ -97,15 +100,10 @@
97 super(SlaveOnlyDatabasePolicyTestCase, self).setUp()
98
99 def test_master_allowed(self):
100- # The master store is not allowed here, but we need this empty test
101- # to overwrite the test method from our parent class, where the master
102- # store is allowed.
103- pass
104-
105- def test_master_not_allowed(self):
106- self.failUnlessRaises(
107- DisallowedStore,
108- getUtility(IStoreSelector).get, MAIN_STORE, MASTER_FLAVOR)
109+ for store in ALL_STORES:
110+ self.failUnlessRaises(
111+ DisallowedStore,
112+ getUtility(IStoreSelector).get, store, MASTER_FLAVOR)
113
114
115 class MasterDatabasePolicyTestCase(BaseDatabasePolicyTestCase):
116@@ -129,9 +127,10 @@
117
118 def test_slave_allowed(self):
119 # We get the master store even if the slave was requested.
120- self.assertProvides(
121- getUtility(IStoreSelector).get(MAIN_STORE, SLAVE_FLAVOR),
122- ISlaveStore)
123+ for store in ALL_STORES:
124+ self.assertProvides(
125+ getUtility(IStoreSelector).get(store, SLAVE_FLAVOR),
126+ ISlaveStore)
127
128
129 class LaunchpadDatabasePolicyTestCase(SlaveDatabasePolicyTestCase):
130@@ -245,20 +244,23 @@
131
132 def test_defaults(self):
133 # default Store is the slave.
134- self.assertProvides(
135- getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR),
136- ISlaveStore)
137+ for store in ALL_STORES:
138+ self.assertProvides(
139+ getUtility(IStoreSelector).get(store, DEFAULT_FLAVOR),
140+ ISlaveStore)
141
142 def test_slave_allowed(self):
143- self.assertProvides(
144- getUtility(IStoreSelector).get(MAIN_STORE, SLAVE_FLAVOR),
145- ISlaveStore)
146+ for store in ALL_STORES:
147+ self.assertProvides(
148+ getUtility(IStoreSelector).get(store, SLAVE_FLAVOR),
149+ ISlaveStore)
150
151 def test_master_disallowed(self):
152 store_selector = getUtility(IStoreSelector)
153- self.assertRaises(
154- ReadOnlyModeDisallowedStore,
155- store_selector.get, MAIN_STORE, MASTER_FLAVOR)
156+ for store in ALL_STORES:
157+ self.assertRaises(
158+ ReadOnlyModeDisallowedStore,
159+ store_selector.get, store, MASTER_FLAVOR)
160
161
162 def test_suite():
163

« Back to merge proposal