Merge ~ines-almeida/launchpad:cleanup-after-pro-enable-migration into launchpad:master

Proposed by Ines Almeida
Status: Merged
Approved by: Ines Almeida
Approved revision: f64689d3c062f3aabf5fb460fc6a970d6c62034c
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~ines-almeida/launchpad:cleanup-after-pro-enable-migration
Merge into: launchpad:master
Diff against target: 351 lines (+3/-218)
5 files modified
lib/lp/scripts/garbo.py (+0/-32)
lib/lp/scripts/tests/test_garbo.py (+0/-42)
lib/lp/snappy/interfaces/snap.py (+0/-11)
lib/lp/snappy/model/snap.py (+3/-58)
lib/lp/snappy/tests/test_snap.py (+0/-75)
Reviewer Review Type Date Requested Status
Jürgen Gmach Approve
Review via email: mp+466137@code.launchpad.net

Commit message

Cleanup after snap.pro_enable migration

The migration has finishied months ago. This removes the garbo jobs and the auxiliary code that was added to aid the migration.
We also set the 'pro_enable' attribute as non-null now that there are no longer any null values in our databases.

Description of the change

All tests in `snappy.tests` have run successfully.

This is related to this DB MP: https://code.launchpad.net/~ines-almeida/launchpad/+git/launchpad/+merge/457147

And to this Jira ticket: https://warthogs.atlassian.net/browse/LP-1350

I will request for the following query to be run in production before merging this MP, for a last sanity check:
`SELECT pro_enable, Count(*) FROM Snap GROUP BY pro_enable;`

This query returned no null values in December 8th 2023.

To post a comment you must log in.
Revision history for this message
Jürgen Gmach (jugmac00) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/scripts/garbo.py b/lib/lp/scripts/garbo.py
2index 61cd51b..d4fa136 100644
3--- a/lib/lp/scripts/garbo.py
4+++ b/lib/lp/scripts/garbo.py
5@@ -116,8 +116,6 @@ from lp.services.verification.model.logintoken import LoginToken
6 from lp.services.webapp.publisher import canonical_url
7 from lp.services.webhooks.interfaces import IWebhookJobSource
8 from lp.services.webhooks.model import WebhookJob
9-from lp.snappy.interfaces.snap import ISnapSet
10-from lp.snappy.model.snap import Snap
11 from lp.snappy.model.snapbuild import SnapFile
12 from lp.snappy.model.snapbuildjob import SnapBuildJobType
13 from lp.soyuz.enums import (
14@@ -2261,35 +2259,6 @@ class ArchiveFileDatePopulator(TunableLoop):
15 transaction.commit()
16
17
18-class SnapProEnablePopulator(TunableLoop):
19- """Populates Snap.pro_enable."""
20-
21- maximum_chunk_size = 100
22-
23- def __init__(self, log, abort_time=None):
24- super().__init__(log, abort_time)
25- self.start_at = 1
26- self.store = IPrimaryStore(Snap)
27-
28- def findSnaps(self):
29- snaps = self.store.find(
30- Snap,
31- Snap.id >= self.start_at,
32- Snap._pro_enable == None,
33- )
34- return snaps.order_by(Snap.id)
35-
36- def isDone(self):
37- return self.findSnaps().is_empty()
38-
39- def __call__(self, chunk_size):
40- snaps = list(self.findSnaps()[:chunk_size])
41- for snap in snaps:
42- snap._pro_enable = getUtility(ISnapSet).inferProEnable(snap.source)
43- self.start_at = snaps[-1].id + 1
44- transaction.commit()
45-
46-
47 class BaseDatabaseGarbageCollector(LaunchpadCronScript):
48 """Abstract base class to run a collection of TunableLoops."""
49
50@@ -2626,7 +2595,6 @@ class DailyDatabaseGarbageCollector(BaseDatabaseGarbageCollector):
51 ScrubPOFileTranslator,
52 SnapBuildJobPruner,
53 SnapFilePruner,
54- SnapProEnablePopulator,
55 SourcePackagePublishingHistoryFormatPopulator,
56 SuggestiveTemplatesCacheUpdater,
57 TeamMembershipPruner,
58diff --git a/lib/lp/scripts/tests/test_garbo.py b/lib/lp/scripts/tests/test_garbo.py
59index 8aee9c5..a5a16e0 100644
60--- a/lib/lp/scripts/tests/test_garbo.py
61+++ b/lib/lp/scripts/tests/test_garbo.py
62@@ -60,7 +60,6 @@ from lp.code.model.codeimportresult import CodeImportResult
63 from lp.code.model.diff import Diff
64 from lp.code.model.gitjob import GitJob, GitRefScanJob
65 from lp.code.model.gitrepository import GitRepository
66-from lp.code.tests.helpers import GitHostingFixture
67 from lp.oci.interfaces.ocirecipe import OCI_RECIPE_ALLOW_CREATE
68 from lp.oci.model.ocirecipebuild import OCIFile
69 from lp.registry.enums import BranchSharingPolicy, BugSharingPolicy, VCSType
70@@ -2585,47 +2584,6 @@ class TestGarbo(FakeAdapterMixin, TestCaseWithFactory):
71 self.assertEqual(1, rs.count())
72 self.assertEqual(archive_files[1], rs.one())
73
74- def test_SnapProEnablePopulator(self):
75- switch_dbuser("testadmin")
76- refs = [self.factory.makeGitRefs()[0] for _ in range(4)]
77- blobs = {
78- ref.repository.getInternalPath(): blob
79- for ref, blob in (
80- (refs[0], b"name: test-snap\n"),
81- (refs[1], b"name: test-snap\nbase: core\n"),
82- (refs[2], b"name: test-snap\nbase: core18\n"),
83- )
84- }
85- self.useFixture(GitHostingFixture()).getBlob = (
86- lambda path, *args, **kwargs: blobs.get(path)
87- )
88- old_snaps = [self.factory.makeSnap(git_ref=ref) for ref in refs]
89- for snap in old_snaps:
90- removeSecurityProxy(snap)._pro_enable = None
91- try:
92- Store.of(old_snaps[0]).flush()
93- except IntegrityError:
94- # Now enforced by DB NOT NULL constraint; backfilling is no
95- # longer necessary.
96- return
97-
98- new_snaps = [
99- self.factory.makeSnap(pro_enable=False),
100- self.factory.makeSnap(pro_enable=True),
101- ]
102- transaction.commit()
103-
104- self.runDaily()
105-
106- # Old snap recipes are backfilled.
107- self.assertIs(True, removeSecurityProxy(old_snaps[0])._pro_enable)
108- self.assertIs(True, removeSecurityProxy(old_snaps[1])._pro_enable)
109- self.assertIs(False, removeSecurityProxy(old_snaps[2])._pro_enable)
110- self.assertIs(False, removeSecurityProxy(old_snaps[3])._pro_enable)
111- # Other snap recipes are left alone.
112- self.assertIs(False, removeSecurityProxy(new_snaps[0])._pro_enable)
113- self.assertIs(True, removeSecurityProxy(new_snaps[1])._pro_enable)
114-
115
116 class TestGarboTasks(TestCaseWithFactory):
117 layer = LaunchpadZopelessLayer
118diff --git a/lib/lp/snappy/interfaces/snap.py b/lib/lp/snappy/interfaces/snap.py
119index 8364c58..722d6d1 100644
120--- a/lib/lp/snappy/interfaces/snap.py
121+++ b/lib/lp/snappy/interfaces/snap.py
122@@ -1301,17 +1301,6 @@ class ISnapSet(Interface):
123 ):
124 """Whether or not the information type context is valid."""
125
126- def inferProEnable(context):
127- """Infer a backward-compatible setting of pro_enable.
128-
129- New snap recipes only build using dependencies from Ubuntu Pro if
130- explicitly configured to do so, but historically we enabled this by
131- default for snap recipes based on "core" (i.e. Ubuntu Core 16). For
132- backward compatibility, we continue doing this until we have
133- self-service Pro enablement for snap recipes; see
134- https://docs.google.com/document/d/19juEP2pOsww4t9Z-jtVZbJdUHgZqkmE9mRukGBQ8DHk.
135- """
136-
137 @operation_parameters(
138 owner=Reference(IPerson, title=_("Owner"), required=True),
139 name=TextLine(title=_("Snap name"), required=True),
140diff --git a/lib/lp/snappy/model/snap.py b/lib/lp/snappy/model/snap.py
141index cf18262..8553b3e 100644
142--- a/lib/lp/snappy/model/snap.py
143+++ b/lib/lp/snappy/model/snap.py
144@@ -67,7 +67,6 @@ from lp.code.errors import (
145 )
146 from lp.code.interfaces.branch import IBranch
147 from lp.code.interfaces.branchcollection import IAllBranches, IBranchCollection
148-from lp.code.interfaces.branchhosting import InvalidRevisionException
149 from lp.code.interfaces.gitcollection import (
150 IAllGitRepositories,
151 IGitCollection,
152@@ -130,7 +129,6 @@ from lp.services.job.model.job import Job
153 from lp.services.librarian.model import LibraryFileAlias, LibraryFileContent
154 from lp.services.openid.adapters.openid import CurrentOpenIDEndPoint
155 from lp.services.propertycache import cachedproperty, get_property_cache
156-from lp.services.timeout import default_timeout
157 from lp.services.webapp.authorization import precache_permission_for_objects
158 from lp.services.webapp.interfaces import ILaunchBag
159 from lp.services.webapp.publisher import canonical_url
160@@ -394,7 +392,7 @@ class Snap(StormBase, WebhookTargetMixin):
161
162 _store_channels = JSON("store_channels", allow_none=True)
163
164- _pro_enable = Bool(name="pro_enable", allow_none=True)
165+ pro_enable = Bool(name="pro_enable", allow_none=False)
166
167 _use_fetch_service = Bool(name="use_fetch_service", allow_none=False)
168
169@@ -458,7 +456,7 @@ class Snap(StormBase, WebhookTargetMixin):
170 self.store_name = store_name
171 self.store_secrets = store_secrets
172 self.store_channels = store_channels
173- self._pro_enable = pro_enable
174+ self.pro_enable = pro_enable
175 self.use_fetch_service = use_fetch_service
176
177 def __repr__(self):
178@@ -687,18 +685,6 @@ class Snap(StormBase, WebhookTargetMixin):
179 def store_channels(self, value):
180 self._store_channels = value or None
181
182- # XXX ines-almeida 2023-10-18: Simplify this once the database column has
183- # been backfilled.
184- @property
185- def pro_enable(self):
186- if self._pro_enable is None:
187- return getUtility(ISnapSet).inferProEnable(self.source)
188- return self._pro_enable
189-
190- @pro_enable.setter
191- def pro_enable(self, value):
192- self._pro_enable = value
193-
194 @property
195 def use_fetch_service(self):
196 if getFeatureFlag(SNAP_USE_FETCH_SERVICE_FEATURE_FLAG):
197@@ -1550,7 +1536,7 @@ class SnapSet:
198 store_secrets=None,
199 store_channels=None,
200 project=None,
201- pro_enable=None,
202+ pro_enable=False,
203 use_fetch_service=False,
204 ):
205 """See `ISnapSet`."""
206@@ -1608,9 +1594,6 @@ class SnapSet:
207 ):
208 raise SnapPrivacyMismatch
209
210- if pro_enable is None:
211- pro_enable = self.inferProEnable(branch or git_ref)
212-
213 store = IPrimaryStore(Snap)
214 snap = Snap(
215 registrant,
216@@ -1674,44 +1657,6 @@ class SnapSet:
217
218 return True
219
220- # XXX ines-almeida 2023-10-18: Remove this once we have self-service Pro
221- # enablement for snap recipes.
222- def inferProEnable(self, context):
223- """See `ISnapSet`."""
224- if context is None:
225- # Recipe has been detached from its source.
226- return False
227-
228- try:
229- # Ensure there is a reasonable timeout set. Without this, the
230- # default in snap builds would be 'None', which we don't want.
231- with default_timeout(300.0):
232- snapcraft_data = self.getSnapcraftYaml(context)
233- except (
234- MissingSnapcraftYaml,
235- CannotFetchSnapcraftYaml,
236- CannotParseSnapcraftYaml,
237- InvalidRevisionException,
238- ):
239- pass
240- else:
241- base = snapcraft_data.get("base")
242- build_base = snapcraft_data.get("build-base")
243- name = snapcraft_data.get("name")
244- snap_type = snapcraft_data.get("type")
245-
246- if build_base is not None:
247- snap_base_name = build_base
248- elif name is not None and snap_type == "base":
249- snap_base_name = name
250- else:
251- snap_base_name = base
252-
253- if snap_base_name is None or snap_base_name == "core":
254- return True
255-
256- return False
257-
258 def _getByName(self, owner, name):
259 return (
260 IStore(Snap)
261diff --git a/lib/lp/snappy/tests/test_snap.py b/lib/lp/snappy/tests/test_snap.py
262index 7aa8c29..c85839d 100644
263--- a/lib/lp/snappy/tests/test_snap.py
264+++ b/lib/lp/snappy/tests/test_snap.py
265@@ -3725,86 +3725,11 @@ class TestSnapProcessors(TestCaseWithFactory):
266 distro_series=self.factory.makeDistroSeries(),
267 name=self.factory.getUniqueUnicode("snap-name"),
268 git_ref=git_ref,
269- pro_enable=None,
270 )
271
272 snap = getUtility(ISnapSet).new(**components)
273 self.assertFalse(snap.pro_enable)
274
275- def test_inferProEnable(self):
276- """inferProEnable returns expected bool value depending on context:
277- - Context and snapcraft.yaml file exist, and no base - True
278- - Context and snapcraft.yaml file exist, and base is 'core' - True
279- - Else, default to False
280- """
281-
282- refs = [self.factory.makeGitRefs()[0] for _ in range(7)]
283- blobs = {
284- ref.repository.getInternalPath(): blob
285- for ref, blob in (
286- (refs[0], b"name: test-snap\n"),
287- (refs[1], b"name: test-snap\nbase: core\n"),
288- (refs[2], b"name: test-snap\nbase: core18\n"),
289- (refs[3], b"name: test-snap\nbuild-base: devel\n"),
290- (refs[4], b"name: core\ntype: base\n"),
291- (refs[5], b"name: core18\ntype: base\n"),
292- )
293- }
294- self.useFixture(GitHostingFixture()).getBlob = (
295- lambda path, *args, **kwargs: blobs.get(path)
296- )
297-
298- inferProEnable = getUtility(ISnapSet).inferProEnable
299- self.assertTrue(inferProEnable(refs[0])) # Snap with no base
300- self.assertTrue(inferProEnable(refs[1])) # Snap with 'core' base
301- self.assertFalse(inferProEnable(refs[2])) # Snap with 'core18' base
302- self.assertFalse(inferProEnable(refs[3])) # Snap with only build-base
303- self.assertTrue(inferProEnable(refs[4])) # 'core' snap itself
304- self.assertFalse(inferProEnable(refs[5])) # 'core18' snap itself
305- self.assertFalse(inferProEnable(refs[6])) # Snap w/out snapcraft.yaml
306- self.assertFalse(inferProEnable(None)) # Snap w/out ref or branch
307-
308- def test_inferProEnable_branches(self):
309- """With a branch as a context, inferProEnable returns the inferred
310- values for pro-enable as expected (see test description above)
311- """
312- branches = [
313- removeSecurityProxy(self.factory.makeBranch()) for _ in range(7)
314- ]
315- blobs = {
316- branch.id: blob
317- for branch, blob in (
318- (branches[0], b"name: test-snap\n"),
319- (branches[1], b"name: test-snap\nbase: core\n"),
320- (branches[2], b"name: test-snap\nbase: core18\n"),
321- (branches[3], b"name: test-snap\nbuild-base: devel\n"),
322- (branches[4], b"name: core\ntype: base\n"),
323- (branches[5], b"name: core18\ntype: base\n"),
324- )
325- }
326- self.useFixture(BranchHostingFixture()).getBlob = (
327- lambda branch_id, *args, **kwargs: blobs.get(branch_id)
328- )
329-
330- inferProEnable = getUtility(ISnapSet).inferProEnable
331- self.assertTrue(inferProEnable(branches[0])) # Snap w no base
332- self.assertTrue(inferProEnable(branches[1])) # Snap w 'core' base
333- self.assertFalse(inferProEnable(branches[2])) # Snap w 'core18' base
334- self.assertFalse(inferProEnable(branches[3])) # Snap w only build-base
335- self.assertTrue(inferProEnable(branches[4])) # 'core' snap itself
336- self.assertFalse(inferProEnable(branches[5])) # 'core18' snap itself
337- self.assertFalse(inferProEnable(branches[6])) # w/out snapcraft.yaml
338- self.assertFalse(inferProEnable(None)) # w/out ref or branch
339-
340- def test_inferProEnable_bad_revision(self):
341- """A branch with an invalid revision ID (or an invalid last_scanned_id)
342- will have its pro-enable value set to False.
343- """
344- branch = self.factory.makeBranch()
345- branch.last_scanned_id = "bad/revision"
346- inferProEnable = getUtility(ISnapSet).inferProEnable
347- self.assertFalse(inferProEnable(removeSecurityProxy(branch)))
348-
349
350 class TestSnapWebservice(TestCaseWithFactory):
351 layer = LaunchpadFunctionalLayer

Subscribers

People subscribed via source and target branches

to status/vote changes: