[
https://issues.apache.org/jira/browse/BROOKLYN-492?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15993947#comment-15993947
]
Alex Heneveld commented on BROOKLYN-492:
----------------------------------------
The hack workaround suggestion was to have two files claiming identical
versions but with different ranges on the Import-Package so that only the right
one can be resolved, avoiding indeterminacy. But you are correct Karaf doesn't
let you have two installed bundles with the same name+version so that's out.
But maybe that idea will work with an extra dependency?
Let's say the problem is this:
* Author has a bundle {{my_java:1.0}} which depends on {{brooklyn}} version
0.11, and a catalog item {{foo}} which requires code in {{my_java}} in package
{{org.my_java}}, and this catalog item is declared in a catalog BOM depending
on library {{http:://artifactory/path/to/my_java_1.0.jar}}
* User has deployed an instance of {{foo}} to a brooklyn 0.11 server
* Operator wants to update the brooklyn server to 0.12 -- but {{my_java:1.0}}
doesn't work with 0.12, that bundle won't install, and as a result {{foo}}
fails to rebind (or possibly fails after rebind)
Could a manual workaround be as follows:
# Author creates a new bundle {{my_java_real:1.0}} containing the java
currently in {{my_java}}, and ensures that bundle depends on
{{brooklyn:[0.11,0.12)}} (e.g. through an imports-package statement)
# Author creates an upgrade to that bundle in {{my_java_real:1.1}} which
depends on (and is compatible with) {{brooklyn:[0.12,0.13)}}
# Author creates a new {{my_java}} which {{Import-Package: org.my_java}} (any
version) and exports the same package
# Author installs this new {{my_java}} at the URL referenced in the BOM --
masking it
# Operator installs both {{my_java_real:1.0}} and {{my_java_real:1.1}} into
their brooklyn container and uninstalls any existing (old) {{my_java}} -- which
version of the brooklyn container doesn't matter and of course one of the
{{my_java_real}} versions won't be resolvable but that's going to be okay
# Operator now rebinds to existing state (possibly a rebind was attempted
previously and failed, but at least it provided an opportunity to install the
{{my_java_real}} bundles into their container; this should pull down the new
{{my_java}} which will then resolve the correct {{my_java_real}}
It's a bit tedious, it means manually installing dependency bundles, and
swapping the {{my_java}} URL is ugly but:
* This gives a technique that works with either Brooklyn version
* It doesn't require the *user* to do anything
* It doesn't require doing anything to persisted state
For a v2 of {{foo}} I'd say to put {{foo}} and the BOM into in an OSGi bundle
which declares a {{MANIFEST.MF}} dependency to {{Import-Package: org.my_java}};
this removes the need for the intermediate {{my_java}} bundle and means
Brooklyn doesn't have to track any dependencies and versions, plus it means we
don't need to update {{foo}} on a Brooklyn version change. This doesn't solve
the problem that we need the appropriate {{my_java_real}} bundle installed, but
there are quite a few options -- simplest is to say to install it into the old
version of Brooklyn, and give an option not to start it (or by default don't
start if there is no {{catalog.bom}} contained inside) -- though in any case it
feels like we could live without that.
There will be times when we _do_ need to update {{foo}} on a Brooklyn version
change. Ideally there should be a {{foo}} that works with multiple Brooklyn
versions so we can install new {{foo}} into old-version Brooklyn instance, then
we have a way to mark old {{foo}} as deprecated, then upgrade all old {{foo}}
instances, then start new Brooklyn version. But we should think through the
case when {{foo}} _can't_ work with multiple Brooklyn versions; eg {{foo:2}}
works with {{brooklyn:0.12}} and {{foo:3}} with {{brooklyn:0.13}}. One
technique could be to install {{foo:3}} into the {{brooklyn:0.12}} container
but with some sort of "optional" flag so it doesn't complain if it can't
resolve. We then have a boot-time (or pre-rebind) way when starting
{{brooklyn:0.13}} to say: "mark {{foo:2}} optional and deprecated, and mark
{{foo:3}} not optional, and upgrade all deprecated things".
I still think the proposal and leaning more on OSGi largely solves things. I
definitely prefer that over copy-state transformations!
> Brooklyn upgrade tricky if using `brooklyn.libraries` for custom OSGi bundles
> -----------------------------------------------------------------------------
>
> Key: BROOKLYN-492
> URL: https://issues.apache.org/jira/browse/BROOKLYN-492
> Project: Brooklyn
> Issue Type: Bug
> Reporter: Aled Sage
>
> When a user refers to their custom OSGi bundle in a catalog's
> {{brooklyn.libraries}} section, this could make subsequent upgrade of
> Brooklyn more difficult.
> This is separate from Alex's email thread to dev@brooklyn "Making blueprint
> upgrades easier - feature proposal" (i.e. it would not be solved by Alex's
> proposal). However, it's worth thinking about that as well for a long-term
> holistic solution.
> ---
> Consider the following steps:
> * With Brooklyn 0.11.0:
> * A user writes a custom OSGi bundle (e.g. containing their own custom
> policy or Java entity or whatever), compiled against Brooklyn 0.11.0.
> * The user creates a catalog item (v1.0), which references that bundle.
> * The user deploys some apps that use this catalog item (with their state
> being persisted).
> * When Brooklyn 0.12.0 comes out, the user attempts to upgrade:
> * The user tries to start 0.12.0, rebinding against their existing
> persisted state. This reads the catalog, and thus attempts to install/active
> the user's custom OSGi bundle.
> * Their custom bundle may fail to install (e.g. perhaps there are wiring
> errors due to dependency changes between 0.11.0 and 0.12.0);
> or alternatively perhaps the bundle loads, but the instances of the Java
> policy/entity fail to be instantiated (e.g. 0.11.0 and 0.12.0 are not binary
> compatible, with the user's code relying on some class/method that has
> changed).
> * Rebind therefore might fails.
> * The user tries to update their custom OSGi bundle:
> * The user updates their code and recompiles, to create a v2.0 of their
> bundle and of their catalog item.
> * However, they can't start 0.12.0 with the existing persisted state in
> order to add the v2.0 catalog item, and upgrade their entities.
> * The user might then try starting 0.11.0 up instead, and adding v2.0 of
> the catalog item there.
> This might work, or it might lead to bundle wiring errors because v2.0 is
> incompatible with Brooklyn 0.11.0.
> How likely this is to actually impact a user depends on: 1) what binary
> incompatible changes we might make in Brooklyn between versions; and 2) what
> parts of Brooklyn the user's Java code makes use of. Some power-users do some
> pretty sophisticated things, digging into the less frequented classes of
> Brooklyn that on first blush might not be considered part of our "api"!
> ---
> The long-term solution needs a lot more discussion on the dev@brooklyn
> mailing list.
> However, it might well revolve around being able to start Brooklyn into a
> usable state, even when some blueprints/entities have errors. This is
> important so that errors can be resolved, and so that errors in some
> blueprints don't cause the entire server to become unusable.
> This is particularly important for big companies using Brooklyn, where there
> is a separation of teams: one team responsible for managing Brooklyn
> servers/upgrades, and other teams responsible for writing blueprints /
> catalog items.
> ---
> A short-term solution could involve using offline tools to transform the
> persisted state (e.g. using something like {{bin/brooklyn copy-state ...
> --transformations ...}}).
> Note that the {{copy-state}} commands are not readily available if one is
> using just the Karaf distro of Brooklyn.
> Also note that {{./bin/brooklyn launch --catalogAdd ...}} is also not
> available if using the Karaf distro of Brooklyn.
--
This message was sent by Atlassian JIRA
(v6.3.15#6346)