Merge lp:~wgrant/launchpad/bug-1043319 into lp:launchpad

Proposed by William Grant on 2012-08-29
Status: Merged
Approved by: Curtis Hovey on 2012-08-29
Approved revision: no longer in the source branch.
Merged at revision: 15877
Proposed branch: lp:~wgrant/launchpad/bug-1043319
Merge into: lp:launchpad
Diff against target: 122 lines (+40/-20)
2 files modified
lib/lp/scripts/garbo.py (+9/-9)
lib/lp/scripts/tests/test_garbo.py (+31/-11)
To merge this branch: bzr merge lp:~wgrant/launchpad/bug-1043319
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code 2012-08-29 Approve on 2012-08-29
Review via email: mp+121874@code.launchpad.net

Commit Message

Fix UnusedSharingPolicyPruner to correctly preserve access policies when they're allowed by a sharing policy.

Description of the Change

UnusedSharingPolicyPruner is meant to keep any access policies that are in use by artifacts, or allowed by the project sharing policy. The first bit works fine, but the sharing policy bit is buggy: it calculates the set difference between the extant access policies and the allowed types, but those are different types of object. It needs to instead find the access policies that have types not in the allowed set.

I rewrote the test to verify all three cases (deleted, kept by sharing policy, and kept by artifact), and renamed the pruner to UnusedAccessPolicyPruner to more accurately reflect its true purpose.

To post a comment you must log in.
Curtis Hovey (sinzui) wrote :

Thank you.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/scripts/garbo.py'
2--- lib/lp/scripts/garbo.py 2012-08-28 15:29:23 +0000
3+++ lib/lp/scripts/garbo.py 2012-08-29 14:22:30 +0000
4@@ -1067,13 +1067,13 @@
5 transaction.commit()
6
7
8-class UnusedSharingPolicyPruner(TunableLoop):
9+class UnusedAccessPolicyPruner(TunableLoop):
10 """Deletes unused AccessPolicy and AccessPolicyGrants for products."""
11
12 maximum_chunk_size = 5000
13
14 def __init__(self, log, abort_time=None):
15- super(UnusedSharingPolicyPruner, self).__init__(log, abort_time)
16+ super(UnusedAccessPolicyPruner, self).__init__(log, abort_time)
17 self.start_at = 1
18 self.store = IMasterStore(Product)
19
20@@ -1087,23 +1087,23 @@
21 def __call__(self, chunk_size):
22 products = list(self.findProducts()[:chunk_size])
23 for product in products:
24- allowed_bug_policies = set(
25+ allowed_bug_types = set(
26 BUG_POLICY_ALLOWED_TYPES.get(
27 product.bug_sharing_policy, FREE_INFORMATION_TYPES))
28- allowed_branch_policies = set(
29+ allowed_branch_types = set(
30 BRANCH_POLICY_ALLOWED_TYPES.get(
31 product.branch_sharing_policy, FREE_INFORMATION_TYPES))
32+ allowed_types = allowed_bug_types.union(allowed_branch_types)
33 # Fetch all APs, and after filtering out ones that are forbidden
34 # by the bug and branch policies, the APs that have no APAs are
35 # unused and can be deleted.
36 access_policies = set(
37 getUtility(IAccessPolicySource).findByPillar([product]))
38- candidate_aps = access_policies.difference(
39- allowed_bug_policies, allowed_branch_policies)
40 apa_source = getUtility(IAccessPolicyArtifactSource)
41 unused_aps = [
42- ap for ap in candidate_aps
43- if apa_source.findByPolicy([ap]).is_empty()]
44+ ap for ap in access_policies
45+ if ap.type not in allowed_types
46+ and apa_source.findByPolicy([ap]).is_empty()]
47 getUtility(IAccessPolicyGrantSource).revokeByPolicy(unused_aps)
48 for ap in unused_aps:
49 self.store.remove(ap)
50@@ -1398,8 +1398,8 @@
51 SuggestiveTemplatesCacheUpdater,
52 POTranslationPruner,
53 UnlinkedAccountPruner,
54+ UnusedAccessPolicyPruner,
55 UnusedPOTMsgSetPruner,
56- UnusedSharingPolicyPruner,
57 ]
58 experimental_tunable_loops = [
59 PersonPruner,
60
61=== modified file 'lib/lp/scripts/tests/test_garbo.py'
62--- lib/lp/scripts/tests/test_garbo.py 2012-08-28 15:29:23 +0000
63+++ lib/lp/scripts/tests/test_garbo.py 2012-08-29 14:22:30 +0000
64@@ -58,6 +58,7 @@
65 from lp.registry.enums import (
66 BranchSharingPolicy,
67 BugSharingPolicy,
68+ InformationType,
69 )
70 from lp.registry.interfaces.accesspolicy import IAccessPolicySource
71 from lp.registry.interfaces.person import IPersonSet
72@@ -1084,20 +1085,39 @@
73 self.assertEqual(
74 BugSharingPolicy.PUBLIC, product.bug_sharing_policy)
75
76- def test_UnusedSharingPolicyPruner(self):
77- # UnusedSharingPolicyPruner destroys the unused sharing details.
78+ def getAccessPolicyTypes(self, pillar):
79+ return [
80+ ap.type
81+ for ap in getUtility(IAccessPolicySource).findByPillar([pillar])]
82+
83+ def test_UnusedAccessPolicyPruner(self):
84+ # UnusedAccessPolicyPruner removes access policies that aren't
85+ # in use by artifacts or allowed by the project sharing policy.
86 switch_dbuser('testadmin')
87- product = self.factory.makeProduct(
88- branch_sharing_policy=BranchSharingPolicy.PROPRIETARY)
89- ap = self.factory.makeAccessPolicy(pillar=product)
90+ product = self.factory.makeProduct()
91+ self.factory.makeCommercialSubscription(product=product)
92+ with person_logged_in(product.owner):
93+ product.setBugSharingPolicy(BugSharingPolicy.PROPRIETARY)
94+ product.setBranchSharingPolicy(BranchSharingPolicy.PROPRIETARY)
95+ [ap] = getUtility(IAccessPolicySource).find(
96+ [(product, InformationType.PRIVATESECURITY)])
97 self.factory.makeAccessPolicyArtifact(policy=ap)
98- self.factory.makeAccessPolicyGrant(policy=ap)
99- all_aps = getUtility(IAccessPolicySource).findByPillar([product])
100- # There are 3 because two are created implicitly when the product is.
101- self.assertEqual(3, all_aps.count())
102+
103+ # Private and Private Security were created with the project.
104+ # Proprietary was created when the branch sharing policy was set.
105+ self.assertContentEqual(
106+ [InformationType.PRIVATESECURITY, InformationType.USERDATA,
107+ InformationType.PROPRIETARY],
108+ self.getAccessPolicyTypes(product))
109+
110 self.runDaily()
111- all_aps = getUtility(IAccessPolicySource).findByPillar([product])
112- self.assertEqual([ap], list(all_aps))
113+
114+ # Proprietary is permitted by the sharing policy, and there's a
115+ # Private Security artifact. But Private isn't in use or allowed
116+ # by a sharing policy, so garbo deleted it.
117+ self.assertContentEqual(
118+ [InformationType.PRIVATESECURITY, InformationType.PROPRIETARY],
119+ self.getAccessPolicyTypes(product))
120
121
122 class TestGarboTasks(TestCaseWithFactory):