[Zope-CMF] GenericSetup proposal: upgrade profiles
Maurits van Rees
m.van.rees at zestsoftware.nl
Tue Jun 23 20:42:35 EDT 2009
Hi,
Products.GenericSetup/interfaces.py says:
BASE, EXTENSION = 1, 2
I propose adding another one:
UPGRADE = 3
and possibly a fourth one:
UNINSTALL = 4
Intro
-----
This refs a small discussion on the Plone developers list at the end
of May, which can be interesting (but not necessary) as background:
http://plone.org/support/forums/core#nabble-tc2966873|a2973467
The meaning should be reasonably clear from the names:
- BASE: completely new install; purge existing settings; usually
applied once during the lifetime of the website: at creation time
- EXTENSION: extend a BASE profile; do not purge existing settings;
might get applied multiple times during the lifetime of the website.
- UPGRADE: upgrade for a BASE or EXTENSION profile; no purge; usually
applied once. Actually, it does not need to be tied to another
profile in any way: it is just a bunch of import steps that need to
be applied once.
- UNINSTALL: undo what was done while applying another profile (BASE,
EXTENSION or less likely an UPGRADE); no purge; usually applied once:
when uninstalling the product that the profile belongs to.
- Hm, let's throw TEST (value 5) in as an idea as well: a non-purging
profile that is meant to be applied during the automated tests but
not during normal use. Can anyone come up with a use case?
- And I suddenly wonder if it is handy to define SNAPSHOT (value 6)
here too. Might this make some of the special handling for
snapshots easier or unnecessary? If someone wants to plea for that:
go ahead. :)
I do not have plans for UNINSTALL, TEST or SNAPSHOT, but I think
UPGRADE would be handy, so let's concentrate on that one.
Proposal
--------
- Add UPGRADE to the GS interfaces.py, for use in the 'provides' line
of a profile registration in zcml:
provides="Products.GenericSetup.interfaces.UPGRADE"
- Show only BASE and EXTENSION profiles and not UPGRADE (or other)
profiles in some parts of the UI, so that those parts are not
cluttered by too many profiles.
Third party products can then register one true EXTENSION profile that
is meant to be applied when installing the product, and several
UPGRADE profiles meant to be applied once, without confusing for
example the CMFQuickInstaller in Plone.
Use case
--------
For our use case we assume that you have made an add-on product. It
has an EXTENSION profile. You have applied the profile in a website.
Now you want to add a catalog index. Your options are:
A. Add this in the current extension profile. This means that any
time you apply this profile this index will be removed and
recreated so you lose data; you need to reindex the index (manually
or in python code - not GenericSetup) and that takes time.
B. Add an upgrade step. Works fine, but this needs python code along
these lines:
indexes = catalog.indexes()
if 'new' not in indexes:
catalog.addIndex('new', 'some_meta_type')
catalog.manage_reindexIndex(ids=['new'])
But why add python code when there is already a perfectly fine
import handler that can read a catalog.xml? We are back to the
dark days before there was GenericSetup then. (Well, okay, writing
python code is not *that* bad. ;-))
C. Add it to the current extension profile. Do not apply this profile
ever again: only once at install time. Instead add an upgrade step
that applies the catalog step from this profile. But this has
basically the same problem as option A: if you later add a second
catalog index you would need to create a new upgrade step to apply
the catalog step and then your first index would be removed and
recreated empty again.
D. Define a new EXTENSION profile that just has a catalog.xml. Either
go to the import tab of portal_setup to run all steps of that
profile, or create an upgrade step that does this. But this means
that in several spots the list of available profiles gets longer,
which threatens to make it hard to use.
The migration machinery of CMFPlone is moving to the
plone.app.upgrade package (not released yet), which already defines
about 24 upgrade steps with 11 extension profiles and that will
only increase, potentially one for each point release of Plone.
See http://svn.plone.org/svn/plone/plone.app.upgrade/trunk
(And the CMFQuickInstaller can get confused when a package has more
than one profile; but that is not a problem for this mailing list,
and I expect that in Plone 4 either the CMFQuickInstaller is gone
or it ends up as just a small wrapper around GenericSetup.)
Similar arguments could be made about adding a property to a property
sheet: you only want to do that once and not override any changes made
to that property by a site admin when you reapply the profile.
So I think another option would help:
E. Define an UPGRADE profile that just has a catalog.xml. Going to
the import tab of portal_setup should not list this profile, but
only EXTENSION and BASE profiles, so that list is not so cluttered
anymore. You now just create an upgrade step that applies the
profile.
Implementation
--------------
The biggest changes (which are not actually that big) in GenericSetup
code would be:
- in tool.py make sure that purge is only True for BASE profiles:
def _getImportContext(...):
...
#should_purge = (info.get('type') != EXTENSION)
should_purge = (info.get('type') == BASE)
def listContextInfos(self):
- In registry.py (and tool.py) allow listing only some types, for
example here:
def listProfiles( self, for_=None, types=None ):
if types is None:
# possibly add SNAPSHOT here.
types = [BASE, EXTENSION]
result = []
for profile_id in self._profile_ids:
info = self.getProfileInfo( profile_id )
if for_ is None or issubclass( for_, info['for'] ):
if info['type'] in types:
result.append( profile_id )
return tuple( result )
And then some template changes and of course tests.
As a bonus it may be handy to combine the zcml registration of the
upgrade step and the upgrade profile, but that will be technically
more difficult. Something like this:
<genericsetup:upgradeStep
title="Add catalog index"
description=""
source="1"
destination="2"
directory="profiles/upgrade2"
name="upgrade2"
/>
This would then register directory profiles/upgrade2 as an UPGRADE
profile with name 'upgrade2' and register an upgrade step that applies
that profile. But that is icing on the cake and I am not sure if we
need more zcml constructs here.
I could do these changes (on a branch of course).
Questions
---------
Is this feature interesting for inclusion in GenericSetup?
Is it in scope for 1.5.x?
Is anyone already registering profiles using numbers other than 1
(BASE) or 2 (EXTENSION)?
Do you see a use case for UNINSTALL, TEST, or SNAPSHOT?
Other comments?
Cheers,
--
Maurits van Rees | http://maurits.vanrees.org/
Work | http://zestsoftware.nl/
"This is your day, don't let them take it away." [Barlow Girl]
More information about the Zope-CMF
mailing list