Aled-
Hi -- inline On 22/06/2017 18:51, Aled Sage wrote:
Great list of questions. We don't need these solved now for the immediate proposal but I think we are reaching a consensus even on tricky longer-term issues which is a good sanity check for the proposal and hopefully means more people can work to take us in this direction!+1 to this approach, but I suspect there's a lot more to discuss/plan.
Agree. Main question mark is whether we want to reuse (and expose) OSGi for complex dependency situations e.g. ranges. But we don't need to decide this now._*Leaking OSGi*_I agree with Geoff's worry of us "leaking OSGi". However, we should just "leak" the semantics of bundle dependencies and versioning, which need to be explained to the user. I think we can avoid exposing the OSGi syntax anywhere (except for power-users who want it).
I think packages are wrong here. In Java they're a natural namespace item which existed before bundles (and often repeated in bundles). In our world we don't use packages for most type names and feedback has been people don't want them. The bundles are the namespace -- so "require-bundle" feels like the right OSGi concept._*`brooklyn.libraries` versus `package-imports analogy*_OSGi recommends the use of package-imports, rather than explicitly depending on specific bundles.The analogy for us would be to depend on other catalog item name:versionRange (e.g. in a `brooklyn.imports` section, or whatever). We'd then figure out which bundle to get those from using the same rules as OSGi package-imports.Is it worth exploring further that option, rather than going down the `brooklyn.libraries` route?
(I confess for a while I thought "import-package" was an unnecessary extra layer of abstraction in osgi -- always found the idea cool and technical implementation is awesome but the vast majority of packages come from one bundle anyway. The exceptions I've seen are things like javax.* which really should be in their own bundle. Basing on packages makes the wiring a lot more complicated to understand and debug. However my opinion changed when I realized how clever OSGi is in looking at what dependent packages are _exposed_ by a set of packages: e.g. if B:b.internal.Clazz.method() returns type C:c.Class that makes C a dependency of anything using B, whereas if something just used B:b and not B:b.internal then C is not an exported dependency. Of course with Brooklyn types we don't have or need that level of precision: so I remain at the conclusion that "import-package" would _not_ be worth its weight in our world.)
This argues for being able to configure Brooklyn (Karaf) to be aware of repositories from which dependent bundles can be pulled. I think that gets my vote longer term, instead of URLs. This could be made to work with either `brooklyn.libraries` or `require-bundle`. But again we don't need to decide now._*References Between Bundles*_I don't think long-term the `brooklyn.libraries` should have URLs of other bundles. It could give the name:versionRange of other bundles (which assumes they have somehow already been added to Brooklyn).(Reasoning is that other smart folk don't embed the URLs, presumably because they want people to chose which repo things will come from - e.g. enterprise private repo, versus maven central, etc).
_*Deploying Multiple Bundles*_I lean towards something analogous to the kar file, but maybe lighter weight rather than introducing anything like "features".Really we just need a list of bundle URLs. If someone then deletes one of those bundles, which breaks the other bundles deployed along with it, then tough!
Using repos feels like the best answer to me.
_*Blueprint Validation*_Longer term, it would be nice if we further improved our blueprint validation to ensure all references in a catalog item being added are actually resolvable.Adding to Brooklyn the ability to add a list-of-bundles will no doubt make that harder!
+1
Some of this is already done: we call to OSGi class loaders to find resources, and we track search paths. If we're resolving types we don't currently use the search path; so we need to write something to prefer catalog items whose containingBundle matches something in the search path. We probably also need to augment the search path with dependencies specified through "require-bundle"; I think we currently don't, and we'd need to grab the version OSGi uses. However I don't think we need to implement much more than that._*Incremental Steps?*_This might well prove to be a big change under-the-covers. Things that scare me include: * do we need to re-implement for catalog-items the same dependency/version rules as OSGi uses for class-loading? (+)
* how much will backwards compatibility with historic persisted state make things hard for us.For now we're talking about _preferring_ things in search path. We're not restricting what can be loaded. So persisted state should work the same; you might wind up with a different version of an item in ambiguous cases (but probably you'll get the _right_ version in the new world whereas you'd be getting the _wrong_ version in the old world).
We will be supporting "legacy" catalog items that don't come from a bundle until either those are upgraded or we transparently wrap them in a bundle on upgrade.
It feels incremental already. Do OSGi versions first, then require everything comes from bundles, then we prefer bundle search paths.Are there sensible ways to scope this and de-risk it? Any incremental milestones, which give us incremental value or de-risk it?(+) We could potentially hack something where we synthesise a package/resource per catalog item in our auto-generated bundles, and then ask OSGi where it would load that from! (But that feels like a bad idea, because power-users might add their own bundles directly to karaf.)
Great list. I'd say we're also making type management easier because I can view related types within a bundle._*Business Case (aka value to end-users)*_It would be good to be clearer on the user-value we deliver from this (but please shout if others think that is already clear enough).We're making "upgrades" easier - focusing specifically on deploying a second version of a catalog item, which can then be used (ignoring upgrade of existing app instances for now).We're solving something like the DLL-hell problem (currently, if you don't declare explicit versions within your blueprint, then your blueprint might break when someone else adds a newer version of your dependent blueprint for their own usage). Our current workaround for DLL hell is impractical: hardcode explicit version numbers of your dependencies in the `type: name:version` (no support for version ranges etc, and it would be burried deep within the yaml files).We're making it easier to deploy different versions of a "group of catalog items" (e.g. a big app that is split into several catalog items). Currently (if you didn't hardcode versions in every `type: ...` reference), deploying a 2.0.0 version would likely break a subsequent deployment of the 1.0.0 version, because it would default to the latest for each catalog reference. That is, you'd only get the 1.0.0 version of the main item, and then the 2.0.0 version of each item it referenced.We'd move away from `brooklyn.libraries` hard-coding URLs to other bundles, which most likely goes against the security policies of many enterprises!Is that a fair summary? Anything to add/change?
Aled
Best Alex
On 21/06/2017 09:41, Geoff Macartney wrote:hi Alex,that sounds fair enough. We'll want to add good documentation around whatit means if *everything* is now a bundle (and how we wrap plain catalogs into bundles on users' behalf). We can use the text of your email as a starting point for the docs; it would be good to explain some of the _motivation_ around the choice to make everything a bundle, rather than just say what we do.I do like the idea of version ranges in brooklyn.libraries, but agree it'sbest to proceed in small steps so that would be a later development. Some more questions on implementation details - is it part of this plan to move bundle storage into the persistence location so that HA Brooklyn nodes can find all bundles? - if a catalog.bom (symbolic name xyz) includes brooklyn.libraries andspecifies a remote URL (which gets downloaded), what happens if we deletethe bundle xyz - do the downloaded bundles get "cascade deleted"? GeoffOn Tue, 20 Jun 2017 at 17:22 Alex Heneveld <[email protected]>wrote:Hi Geoff Thanks. Replies to specific points: > whether we are "leaking" an implementation detail (the fact that we use an OSGI runtime) My motivation was to try to minimize this leak. The fact that we use OSGi internally for dependency isolation forces us to use OSGi versions with bundles. But most people most places use the "-qualifier" suffix not ".qualifier", so to accommodate that the proposal suggests a recommended syntax in line with what most people do ("-qualifer") which we can internally safely convert to an OSGi version when needed. There is no need for authors ever to see OSGi and the docs PR doesn't mention OSGi until an "advanced" section. > proposal would rely on Brooklyn moving exclusively to Karaf No. The bundle version format is already a problem with the use of embedded Felix(it solves the problem noted in #672 about needing to use ".qualifer" inyour catalog.bom) > libraries / required-bundle / version ranges Where users want to indicate dependent bundles they currently have the choice of "brooklyn.libraries" (non-osgi) or "require-bundle" (osgi). Both work. We don't need to disable theformer. I'm in two minds about whether we'd want to, at some point, butnot right now of course. An argument for disabling is that it sets up a single canonical way to do things. Yes it means people have to learn OSGi but this is a fairly advanced use case and OSGi is the right tool for the job. If we didn't, it almost certainly means adding version range support in `brooklyn.libraries` which is yet more duplication of what OSGi lets us do. However it would be easier for non-OSGi users(and a lot of OSGi users I bet!) if we did invest in a nice range syntaxin `brooklyn.libraries`. Note `brooklyn.libraries` is the only place where you can specify a URL for a dependent bundle;the OSGi manifest doesn't let you do this (though if using Karaf you canconfigure it to look in a set of repos, which is possibly). It boils down to how we expect people to manage the installation of multiple catalog bundles (URLs v configured repos v something else ... maybe KAR archives which could easily be supported but they're wasteful if the same dependency is included in many KARs).Not sure where we'll want to go with this but it's not something we needto solve for this proposal. HTH Best Alex On 20/06/2017 17:00, Geoff Macartney wrote:hi Alex,In general I think this is a good direction to go in, some questions andthoughts below. One concern is whether we are "leaking" an implementation detail (thefactthat weuse an OSGI runtime) into the specification of what Brooklyn is. I thinkit is good toaim for the improved modularity of having a bundle of catalog definitionsand related resources, all at a given version and added or removed as a unit. I'mlesssure wewant to advertise that all Brooklyn definitions must be contained in OSGIbundles, even if we will wrap them for you. This seems to impose an additional requirement on blueprint authors (learn OSGI) that we don't really want to impose? As an aside, I'm assuming that your proposal would rely on Brooklynmovingexclusively to the Karaf launcher, is that the case? Specific notes inline below. Geoff On Mon, 19 Jun 2017 at 17:39 Alex Heneveld <[email protected]>wrote:Hi All-With bundles now being neatly supported for add and remove, I think it makes sense to use make the "bundle" a first-class concept in managing abrooklyn catalog (type registry). The basic idea is that users will work with ZIPs (or directories if using the br CLI), where a "catalog.bom" is in the root; this is a bundle, and operations like add/remove/update apply to the bundle. Increasingly people are doing this for additions, so it seems prettyobvious that delete should follow suit, and something like a "/bundles"REST endpoint is appropriate.I do like this; as part of this we should re-instate the automaticscanningof bundles for catalog.bom (feature FEATURE_LOAD_BUNDLE_CATALOG_BOM). Now that catalog items can tell you their containing bundle (getContainingBundle()) it should be possible to make this work with rebind.You can still upload just a catalog.bom file; in this proposal it willbe wrapped in a bundle (internally, hidden from user). A bundle name and version will have to be inferred/guessed for backwards compatibility, and probably we should deprecate supplying a BOM which doesn't define a bundle name and version.+1If a ZIP/folder is supplied, it doesn't have to contain any OSGi bundledefinition; that call all be inferred. If a MANIFEST.MF is supplied, any bundle name/version given there must of course match that in the catalog.bom file.Not so sure about that last paragraph - again this is related to leakingIf dependent bundles are declared, they are obeyed atruntime and can be used to find things (pretty much identically to howwe treat "libraries" in the catalog.bom.)the useof OSGI. This would allow someone to write a catalog.bom that would ONLYwork when supplied along with a related manifest (to specify certain dependenciesand so set up the search paths). Do we want to allow that, or should alldefinitionsrequired for entities in a catalog be supplied in the catalog.bom (or itsincluded catalog definitions).* Search Paths - Bundles fix an issue where types have implicit versiondependencies. Consider an "acme-cluster" of "acme-node" entities,defined in a bundle. If I release a 1.0 version of this, and then a 2.0 version, I'd probably expect the 1.0 acme-cluster to load 1.0 acme-node entities, and same for 2.0. But currently any reference to "acme-node"takes the latest version, even if there is a different version in the same bundle. Shifting to bundles, I think we should change this, so that versions of items in the same bundle (or on the OSGi or librarysearch path for that bundle) are preferred over more recent versions inthe repository.+1 this sounds like a better match to what blueprint authors intendagain, how "use OSGI config" - there may be value in specifying ranges(And since we will follow OSGi loading, we can also, ifwe need to, use OSGi config to say that "acme" bundle requires a givenversion _range_ for some other bundle, to have more control over dependency versions when required.)butwe wouldn't want users to have to use OSGI declarations to achieve it.For most users and blueprints this will cause no changes. However thereare some changes to note: * If people have been sloppy with versions or metadata, in most cases they will get a warning * In some cases if uploading a ZIP, the catalog.bom may need to be edited (the upload will give a clear error, and it should not expect rebind)* When a type is referenced with no version, the loading semantics maychange if that type is in the same bundle (this is probably what the user expects) Does anyone oppose any of the above, or have further questions? Best Alex [1] https://github.com/apache/brooklyn-server/pull/672
