← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/remove-snap-store-series-backfill into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/remove-snap-store-series-backfill into lp:launchpad.

Commit message:
Remove migration code for snaps without store_series.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/remove-snap-store-series-backfill/+merge/362459

The only remaining rows on production are one snap that inexplicably sets precise as its distro_series (which will never have a corresponding store_series) and sometimes some snaps created by build.snapcraft.io (fixed by https://github.com/canonical-websites/build.snapcraft.io/pull/1190, but harmless since even before that it sets store_series when authorising the snap store upload).  As such, I think it's OK to simplify things a bit and remove this data migration and its associated support code.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/remove-snap-store-series-backfill into lp:launchpad.
=== modified file 'lib/lp/scripts/garbo.py'
--- lib/lp/scripts/garbo.py	2018-12-17 14:49:53 +0000
+++ lib/lp/scripts/garbo.py	2019-01-30 14:07:49 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2018 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2019 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Database garbage collection."""
@@ -12,7 +12,6 @@
     'save_garbo_job_state',
     ]
 
-from collections import defaultdict
 from datetime import (
     datetime,
     timedelta,
@@ -121,8 +120,6 @@
 from lp.services.verification.model.logintoken import LoginToken
 from lp.services.webhooks.interfaces import IWebhookJobSource
 from lp.services.webhooks.model import WebhookJob
-from lp.snappy.interfaces.snappyseries import ISnappyDistroSeriesSet
-from lp.snappy.model.snap import Snap
 from lp.snappy.model.snapbuild import SnapFile
 from lp.snappy.model.snapbuildjob import SnapBuildJobType
 from lp.soyuz.enums import PackagePublishingStatus
@@ -1614,45 +1611,6 @@
         """ % (SnapBuildJobType.STORE_UPLOAD.value, JobStatus.COMPLETED.value)
 
 
-class SnapStoreSeriesPopulator(TunableLoop):
-    """Populates Snap.store_series based on Snap.distro_series.
-
-    This only touches rows where there is exactly one SnappySeries that
-    could be built from the relevant DistroSeries.
-    """
-
-    maximum_chunk_size = 5000
-
-    def __init__(self, log, abort_time=None):
-        super(SnapStoreSeriesPopulator, self).__init__(log, abort_time)
-        self.start_at = 1
-        self.store = IMasterStore(Snap)
-        all_series_map = defaultdict(list)
-        for sds in getUtility(ISnappyDistroSeriesSet).getAll():
-            all_series_map[sds.distro_series.id].append(sds.snappy_series)
-        self.series_map = {
-            distro_series_id: snappy_serieses[0]
-            for distro_series_id, snappy_serieses in all_series_map.items()
-            if len(snappy_serieses) == 1}
-
-    def findSnaps(self):
-        return self.store.find(
-            Snap,
-            Snap.id >= self.start_at,
-            Snap.distro_series_id.is_in(self.series_map),
-            Snap.store_series == None).order_by(Snap.id)
-
-    def isDone(self):
-        return self.findSnaps().is_empty()
-
-    def __call__(self, chunk_size):
-        snaps = list(self.findSnaps()[:chunk_size])
-        for snap in snaps:
-            snap.store_series = self.series_map[snap.distro_series_id]
-        self.start_at = snaps[-1].id + 1
-        transaction.commit()
-
-
 class BaseDatabaseGarbageCollector(LaunchpadCronScript):
     """Abstract base class to run a collection of TunableLoops."""
     script_name = None  # Script name for locking and database user. Override.
@@ -1945,7 +1903,6 @@
         ScrubPOFileTranslator,
         SnapBuildJobPruner,
         SnapFilePruner,
-        SnapStoreSeriesPopulator,
         SuggestiveTemplatesCacheUpdater,
         TeamMembershipPruner,
         UnlinkedAccountPruner,

=== modified file 'lib/lp/scripts/tests/test_garbo.py'
--- lib/lp/scripts/tests/test_garbo.py	2018-12-17 14:49:53 +0000
+++ lib/lp/scripts/tests/test_garbo.py	2019-01-30 14:07:49 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2018 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2019 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Test the database garbage collector."""
@@ -1606,41 +1606,6 @@
         # retained.
         self._test_SnapFilePruner('foo.snap', None, 30, expected_count=1)
 
-    def test_SnapStoreSeriesPopulator(self):
-        switch_dbuser('testadmin')
-        # Make some series.
-        dses = [self.factory.makeDistroSeries() for _ in range(4)]
-        sses = [
-            self.factory.makeSnappySeries(usable_distro_series=[dses[1]]),
-            self.factory.makeSnappySeries(usable_distro_series=[dses[2]]),
-            self.factory.makeSnappySeries(usable_distro_series=[dses[3]]),
-            self.factory.makeSnappySeries(usable_distro_series=[dses[3]]),
-            ]
-        # Make some snap packages.
-        snaps = [
-            self.factory.makeSnap(distroseries=dses[0]),
-            self.factory.makeSnap(distroseries=dses[1], store_series=sses[1]),
-            self.factory.makeSnap(distroseries=dses[1]),
-            self.factory.makeSnap(distroseries=dses[2], store_series=sses[0]),
-            self.factory.makeSnap(distroseries=dses[2]),
-            self.factory.makeSnap(distroseries=dses[3]),
-            ]
-        transaction.commit()
-
-        self.runDaily()
-
-        # Snaps with no possible store series are untouched.
-        self.assertIsNone(snaps[0].store_series)
-        # Snaps that already have a store series are untouched.
-        self.assertEqual(sses[1], snaps[1].store_series)
-        self.assertEqual(sses[0], snaps[3].store_series)
-        # Snaps with no current store series and exactly one possible store
-        # series have it filled in.
-        self.assertEqual(sses[0], snaps[2].store_series)
-        self.assertEqual(sses[1], snaps[4].store_series)
-        # Snaps with more than one possible store series are untouched.
-        self.assertIsNone(snaps[5].store_series)
-
 
 class TestGarboTasks(TestCaseWithFactory):
     layer = LaunchpadZopelessLayer

=== modified file 'lib/lp/snappy/browser/snap.py'
--- lib/lp/snappy/browser/snap.py	2018-10-09 09:25:19 +0000
+++ lib/lp/snappy/browser/snap.py	2019-01-30 14:07:49 +0000
@@ -750,12 +750,6 @@
     @property
     def initial_values(self):
         initial_values = {}
-        if self.context.store_series is None:
-            # XXX cjwatson 2016-04-26: Remove this case once all existing
-            # Snaps have had a store_series backfilled.
-            sds_set = getUtility(ISnappyDistroSeriesSet)
-            initial_values['store_distro_series'] = sds_set.getByDistroSeries(
-                self.context.distro_series).first()
         if self.context.git_ref is not None:
             initial_values['vcs'] = VCSType.GIT
         else:

=== modified file 'lib/lp/snappy/browser/tests/test_snap.py'
--- lib/lp/snappy/browser/tests/test_snap.py	2018-09-27 13:51:42 +0000
+++ lib/lp/snappy/browser/tests/test_snap.py	2019-01-30 14:07:49 +0000
@@ -667,27 +667,6 @@
             self.snappyseries = self.factory.makeSnappySeries(
                 usable_distro_series=[self.distroseries])
 
-    def test_initial_store_series(self):
-        # The initial store_series is the newest that is usable for the
-        # selected distroseries.
-        development = self.factory.makeUbuntuDistroSeries(
-            version="14.10", status=SeriesStatus.DEVELOPMENT)
-        experimental = self.factory.makeUbuntuDistroSeries(
-            version="15.04", status=SeriesStatus.EXPERIMENTAL)
-        with admin_logged_in():
-            self.factory.makeSnappySeries(
-                usable_distro_series=[development, experimental])
-            newest = self.factory.makeSnappySeries(
-                usable_distro_series=[development])
-            self.factory.makeSnappySeries(usable_distro_series=[experimental])
-        snap = self.factory.makeSnap(distroseries=development)
-        with person_logged_in(self.person):
-            view = create_initialized_view(snap, "+edit")
-        self.assertThat(
-            view.initial_values["store_distro_series"],
-            MatchesStructure.byEquality(
-                snappy_series=newest, distro_series=development))
-
     def test_edit_snap(self):
         old_series = self.factory.makeUbuntuDistroSeries()
         old_branch = self.factory.makeAnyBranch()
@@ -808,8 +787,8 @@
             "Source:\n%s\nEdit snap package" % new_ref.display_name,
             MatchesTagText(content, "source"))
 
-    def setUpDistroSeries(self):
-        """Set up a distroseries with some available processors."""
+    def setUpSeries(self):
+        """Set up {distro,snappy}series with some available processors."""
         distroseries = self.factory.makeUbuntuDistroSeries()
         processor_names = ["386", "amd64", "hppa"]
         for name in processor_names:
@@ -818,8 +797,9 @@
                 distroseries=distroseries, architecturetag=name,
                 processor=processor)
         with admin_logged_in():
-            self.factory.makeSnappySeries(usable_distro_series=[distroseries])
-        return distroseries
+            snappyseries = self.factory.makeSnappySeries(
+                usable_distro_series=[distroseries])
+        return distroseries, snappyseries
 
     def assertSnapProcessors(self, snap, names):
         self.assertContentEqual(
@@ -835,10 +815,10 @@
         self.assertThat(processors_control.controls, MatchesSetwise(*matchers))
 
     def test_display_processors(self):
-        distroseries = self.setUpDistroSeries()
+        distroseries, snappyseries = self.setUpSeries()
         snap = self.factory.makeSnap(
             registrant=self.person, owner=self.person,
-            distroseries=distroseries)
+            distroseries=distroseries, store_series=snappyseries)
         browser = self.getViewBrowser(snap, view_name="+edit", user=snap.owner)
         processors = browser.getControl(name="field.processors")
         self.assertContentEqual(
@@ -847,10 +827,10 @@
         self.assertContentEqual(["386", "amd64", "hppa"], processors.options)
 
     def test_edit_processors(self):
-        distroseries = self.setUpDistroSeries()
+        distroseries, snappyseries = self.setUpSeries()
         snap = self.factory.makeSnap(
             registrant=self.person, owner=self.person,
-            distroseries=distroseries)
+            distroseries=distroseries, store_series=snappyseries)
         self.assertSnapProcessors(snap, ["386", "amd64", "hppa"])
         browser = self.getViewBrowser(snap, view_name="+edit", user=snap.owner)
         processors = browser.getControl(name="field.processors")
@@ -871,10 +851,10 @@
         proc_amd64 = getUtility(IProcessorSet).getByName("amd64")
         proc_armel = self.factory.makeProcessor(
             name="armel", restricted=True, build_by_default=False)
-        distroseries = self.setUpDistroSeries()
+        distroseries, snappyseries = self.setUpSeries()
         snap = self.factory.makeSnap(
             registrant=self.person, owner=self.person,
-            distroseries=distroseries)
+            distroseries=distroseries, store_series=snappyseries)
         snap.setProcessors([proc_386, proc_amd64, proc_armel])
         browser = self.getViewBrowser(snap, view_name="+edit", user=snap.owner)
         processors = browser.getControl(name="field.processors")
@@ -887,7 +867,7 @@
     def test_edit_processors_restricted(self):
         # A restricted processor is shown disabled in the UI and cannot be
         # enabled.
-        distroseries = self.setUpDistroSeries()
+        distroseries, snappyseries = self.setUpSeries()
         proc_armhf = self.factory.makeProcessor(
             name="armhf", restricted=True, build_by_default=False)
         self.factory.makeDistroArchSeries(
@@ -895,7 +875,7 @@
             processor=proc_armhf)
         snap = self.factory.makeSnap(
             registrant=self.person, owner=self.person,
-            distroseries=distroseries)
+            distroseries=distroseries, store_series=snappyseries)
         self.assertSnapProcessors(snap, ["386", "amd64", "hppa"])
         browser = self.getViewBrowser(snap, view_name="+edit", user=snap.owner)
         processors = browser.getControl(name="field.processors")
@@ -921,13 +901,13 @@
         proc_amd64 = getUtility(IProcessorSet).getByName("amd64")
         proc_armhf = self.factory.makeProcessor(
             name="armhf", restricted=True, build_by_default=False)
-        distroseries = self.setUpDistroSeries()
+        distroseries, snappyseries = self.setUpSeries()
         self.factory.makeDistroArchSeries(
             distroseries=distroseries, architecturetag="armhf",
             processor=proc_armhf)
         snap = self.factory.makeSnap(
             registrant=self.person, owner=self.person,
-            distroseries=distroseries)
+            distroseries=distroseries, store_series=snappyseries)
         snap.setProcessors([proc_386, proc_amd64, proc_armhf])
         self.assertSnapProcessors(snap, ["386", "amd64", "armhf"])
         browser = self.getUserBrowser(

=== modified file 'lib/lp/snappy/interfaces/snappyseries.py'
--- lib/lp/snappy/interfaces/snappyseries.py	2016-11-08 16:51:34 +0000
+++ lib/lp/snappy/interfaces/snappyseries.py	2019-01-30 14:07:49 +0000
@@ -179,15 +179,6 @@
         :raises NoSuchSnappySeries: if no snappy series exists with this name.
         """
 
-    @operation_parameters(
-        distro_series=Reference(
-            IDistroSeries, title=_("Distro series"), required=True))
-    @operation_returns_collection_of(ISnappySeries)
-    @export_read_operation()
-    @operation_for_version("devel")
-    def getByDistroSeries(distro_series):
-        """Return all `ISnappySeries` usable with this `IDistroSeries`."""
-
     @collection_default_content()
     def getAll():
         """Return all `ISnappySeries`."""
@@ -196,9 +187,6 @@
 class ISnappyDistroSeriesSet(Interface):
     """Interface representing the set of snappy/distro series links."""
 
-    def getByDistroSeries(distro_series):
-        """Return all `SnappyDistroSeries` for this `IDistroSeries`."""
-
     def getByBothSeries(snappy_series, distro_series):
         """Return a `SnappyDistroSeries` for this pair of series, or None."""
 

=== modified file 'lib/lp/snappy/model/snappyseries.py'
--- lib/lp/snappy/model/snappyseries.py	2016-11-15 14:11:16 +0000
+++ lib/lp/snappy/model/snappyseries.py	2019-01-30 14:07:49 +0000
@@ -197,14 +197,6 @@
             raise NoSuchSnappySeries(name)
         return snappy_series
 
-    def getByDistroSeries(self, distro_series):
-        """See `ISnappySeriesSet`."""
-        rows = IStore(SnappySeries).find(
-            SnappySeries,
-            SnappyDistroSeries.snappy_series_id == SnappySeries.id,
-            SnappyDistroSeries.distro_series == distro_series)
-        return rows.order_by(Desc(SnappySeries.name))
-
     def getAll(self):
         """See `ISnappySeriesSet`."""
         return IStore(SnappySeries).find(SnappySeries).order_by(
@@ -215,15 +207,6 @@
 class SnappyDistroSeriesSet:
     """See `ISnappyDistroSeriesSet`."""
 
-    def getByDistroSeries(self, distro_series):
-        """See `ISnappyDistroSeriesSet`."""
-        store = IStore(SnappyDistroSeries)
-        rows = store.using(SnappyDistroSeries, SnappySeries).find(
-            SnappyDistroSeries,
-            SnappyDistroSeries.snappy_series_id == SnappySeries.id,
-            SnappyDistroSeries.distro_series == distro_series)
-        return rows.order_by(Desc(SnappySeries.name))
-
     def getByBothSeries(self, snappy_series, distro_series):
         """See `ISnappyDistroSeriesSet`."""
         return IStore(SnappyDistroSeries).find(

=== modified file 'lib/lp/snappy/tests/test_snappyseries.py'
--- lib/lp/snappy/tests/test_snappyseries.py	2016-11-15 14:11:16 +0000
+++ lib/lp/snappy/tests/test_snappyseries.py	2019-01-30 14:07:49 +0000
@@ -112,22 +112,6 @@
         self.assertRaises(
             NoSuchSnappySeries, snappy_series_set.getByName, "bar")
 
-    def test_getByDistroSeries(self):
-        dses = [self.factory.makeDistroSeries() for _ in range(3)]
-        snappy_serieses = [self.factory.makeSnappySeries() for _ in range(3)]
-        snappy_serieses[0].usable_distro_series = dses
-        snappy_serieses[1].usable_distro_series = [dses[0], dses[1]]
-        snappy_serieses[2].usable_distro_series = [dses[1], dses[2]]
-        snappy_series_set = getUtility(ISnappySeriesSet)
-        self.assertContentEqual(
-            [snappy_serieses[0], snappy_serieses[1]],
-            snappy_series_set.getByDistroSeries(dses[0]))
-        self.assertContentEqual(
-            snappy_serieses, snappy_series_set.getByDistroSeries(dses[1]))
-        self.assertContentEqual(
-            [snappy_serieses[0], snappy_serieses[2]],
-            snappy_series_set.getByDistroSeries(dses[2]))
-
     def test_getAll(self):
         sample_snappy_serieses = list(IStore(SnappySeries).find(SnappySeries))
         snappy_serieses = [self.factory.makeSnappySeries() for _ in range(3)]
@@ -222,33 +206,6 @@
         self.assertEqual(
             "No such snappy series: 'nonexistent'.", response.body)
 
-    def test_getByDistroSeries(self):
-        # lp.snappy_serieses.getByDistroSeries returns a collection of
-        # matching SnappySeries.
-        person = self.factory.makePerson()
-        webservice = webservice_for_person(
-            person, permission=OAuthPermission.READ_PUBLIC)
-        webservice.default_api_version = "devel"
-        with admin_logged_in():
-            dses = [self.factory.makeDistroSeries() for _ in range(3)]
-            ds_urls = [api_url(ds) for ds in dses]
-            snappy_serieses = [
-                self.factory.makeSnappySeries(name="ss-%d" % i)
-                for i in range(3)]
-            snappy_serieses[0].usable_distro_series = dses
-            snappy_serieses[1].usable_distro_series = [dses[0], dses[1]]
-            snappy_serieses[2].usable_distro_series = [dses[1], dses[2]]
-        for ds_url, expected_snappy_series_names in (
-                (ds_urls[0], ["ss-0", "ss-1"]),
-                (ds_urls[1], ["ss-0", "ss-1", "ss-2"]),
-                (ds_urls[2], ["ss-0", "ss-2"])):
-            response = webservice.named_get(
-                "/+snappy-series", "getByDistroSeries", distro_series=ds_url)
-            self.assertEqual(200, response.status)
-            self.assertContentEqual(
-                expected_snappy_series_names,
-                [entry["name"] for entry in response.jsonBody()["entries"]])
-
     def test_collection(self):
         # lp.snappy_serieses is a collection of all SnappySeries.
         person = self.factory.makePerson()
@@ -273,32 +230,6 @@
         super(TestSnappyDistroSeriesSet, self).setUp()
         self.useFixture(FeatureFixture(SNAP_TESTING_FLAGS))
 
-    def test_getByDistroSeries(self):
-        dses = [self.factory.makeDistroSeries() for _ in range(3)]
-        snappy_serieses = [self.factory.makeSnappySeries() for _ in range(3)]
-        snappy_serieses[0].usable_distro_series = dses
-        snappy_serieses[1].usable_distro_series = [dses[0], dses[1]]
-        snappy_serieses[2].usable_distro_series = [dses[1], dses[2]]
-        sds_set = getUtility(ISnappyDistroSeriesSet)
-        self.assertThat(
-            sds_set.getByDistroSeries(dses[0]),
-            MatchesSetwise(*(
-                MatchesStructure.byEquality(
-                    snappy_series=ss, distro_series=dses[0])
-                for ss in (snappy_serieses[0], snappy_serieses[1]))))
-        self.assertThat(
-            sds_set.getByDistroSeries(dses[1]),
-            MatchesSetwise(*(
-                MatchesStructure.byEquality(
-                    snappy_series=ss, distro_series=dses[1])
-                for ss in snappy_serieses)))
-        self.assertThat(
-            sds_set.getByDistroSeries(dses[2]),
-            MatchesSetwise(*(
-                MatchesStructure.byEquality(
-                    snappy_series=ss, distro_series=dses[2])
-                for ss in (snappy_serieses[0], snappy_serieses[2]))))
-
     def test_getByBothSeries(self):
         dses = [self.factory.makeDistroSeries() for _ in range(2)]
         snappy_serieses = [self.factory.makeSnappySeries() for _ in range(2)]


Follow ups