OSGi bundle remains "installed" without conflicts - osgi

In an OSGi-environment using Apache Felix file-install, one of the bundles does not work.
At first, the bundle does not appear at all; however I can install it manually. It becomes INSTALLED (not RESOLVED as it should):
osgi>install file:///path/to/my/bundle.jar
Bundle id is 230
osgi>diag 230
file:///[...]
No unresolved constraints
osgi>ss <filter>
id State Bundle
230 INSTALLED <bundle-name>
I can start the bundle with start 230, and everything works (services start). After stopping the bundle with stop 230, the bundle is RESOLVED; after update 230 however the bundle enters state INSTALLED again.
How can I identify the cause why the bundle is not RESOLVED automatically?

This is by design:
Installing a bundle will leave it in installed.
When you try to start a bundle, the resolver will first try to resolve it's dependencies, if it succeeds it will transition to resolved and from there to started.
When you stop a bundle, it will transition back to resolved (no need to un-resolve anything at this point as you might want to start it again).
When you update a resolved bundle, regardless of the fact if this is really a different version of the bundle or not, it will be seen as "new" and it will go to installed state.
So in short: updating a resolved bundle will leave the new version of it in installed state by design.

Related

Patching an installation using a bundle oder msi?

I have no experience in patching/upgrading an installation.
We have a wix bundle setup with a standard (wix-created) msi inside which is added to the bundle this way:
<MsiPackage SourceFile="MySetup.msi" Id="MySetupId" Cache="yes" DisplayInternalUI="no" SuppressSignatureVerification ="yes" Visible="no" >
so in Add/Remove software section there is the bundle shown, not the msi itself.
Both, the msi and the bundle, are signed.
Currently our released version is "2.1.0.BuildNumber".
The bundle.wxs has upgrade code A
The msi has product code B and upgrade code C.
Unfortunately this version contains a mean bug but we don't want to release "v2.2.0.BuildNumber" just because of this bug, but "2.1.1.BuildNumber", so we need a patch.
What is be best practise here? Should we just create a msp file described like here
http://wixtoolset.org/documentation/manual/v3/patching/wix_patching.html?
Will this break the relationship between the bundle and the msi? Will this patch be shown in Add/Remove programms section?
Or is there a possibility to use the bundle for a patch?
Goal is, that our customers just can install the patch without deinstalling the old version, but can deinstall the whole scope using the formerly released bundle.
My personal advice is do not create patches unless absolutely necessary. You avoid a lot of trouble. The main problem IMO is that patches do not fit well onto source control and CI. First, you are not able to automatically increase the build number and include it into version number - it must remain the same. Second, creating an msp patch requires the binaries from the previous build be present during the new build. In MS technology the previous msi should be present, in WiX technology you cited you will need *.wixpdb from the previous build. Third (or the first?), the patch is a one-time action which should not be automated for continuous execution by CI.
If the bundle does not include its packages into exe but download them, a new bundle version can download only changed packages so that installation time will be small. Otherwise you are out of luck.
You need to create an msp upgrade for your buggy msi. The upgrade may or may not change the msi version, but if it does then the version of msi will not match the version of the bundle. User does not see msi version anyway.
You can install msp directly. When the bundle is uninstalled, msp will be uninstalled too. I do not know whether the msp will be visible in ARP (msi is not visible).
You may create a patch bundle. This is an independent bundle with its own upgrade code. It will contain
<Bundle .... ParentName="Name of your main bundle"...>
<RelatedBundle Id="YourMainBundleUpgradeCode" Action="Patch" />
Include MspPackage with your msp into the Chain.
This bundle will be visible in Installed Updates as a child of "Name of your main bundle" and it will be uninstalled with the main bundle or when a new version of the main bundle is installed.
You will also need to include a Condition to prevent installation of patch bundle when the main bundle of this particular version is not installed. There is no documented API to detect bundles (although you may use a RegistrySearch), but you may do ProductSearch for particular version of your msi included in main bundle.
Note that a new release of the main bundle with the same version number will install in parallel (there will be two identical entries in ARP) and new release with greater version number will automatically uninstall previous release. Thus, you cannot make new release of the main bundle.

Bundler: Allow user added gems in an UserGemfile

I'm developing a ruby/rails application which should be highly extensible by adding plugins. A plugin is - obviously - a gem, which follows specific roules and contains library code, a rails engine with assets, routes, controllers, views and whatever. Additionally there wille be some kind of API which allows the plugin developer to register custom entries to abstract concepts of the app like adding cronjobs (theres some kind of cron in the main system), adding commands to the CLI and so on.
There will be some 'builtin' plugins containted in the Gemfile shipped with the app due they're part of the app and always activated. And there will be a pool of community written gems which are optional.
Now I'm searching for a possibility to let the user, who installs the app on his machine, addional gems (containing plugins) to the app.
The simplest (but not best) solution would be to say "Just add the plugin gems you want to the Gemfile before running bundle install)". But if there comes an update of the app, the Gemfile would be potentially conflicting and either be resetted or the user have to resolve those conflicts. That's something I don't want actually.
A nicer way would be to say "Hey, here's a UserGemfile, just add the plugin gems you want to that file and run bundle install". That UserGemfile would be listed in the .gitignore and everything would be nice.
Unfortunately it seems like bundler doesn't support something like that.
Do you have any advice how to tackle that issue?
You can do something like this, in, say, import_gems:
puts `cat Gemfile UserGemfile > EffectiveGemfile`
puts `bundle install --gemfile=EffectiveGemfile`
Then, when you run your application, specify the Gemfile:
BUNDLE_GEMFILE=EffectiveGemfile bundle list
Make sure to add EffectiveGemfile and EffectiveGemfile.lock to .gitignore as well.

Ruby/Gem/Bundler Caching my local gem files

I'm working on a gem locally, referenced it using bundle config local.GEMNAME (this is confirmed by the printout of bundle install). However, unless I bump the version on the gem, I can't use the most up-to-date code. When errors occur in the old code, it references the file in the right place, where I have fixed the error. I temporarily had bundler-cache-all switched on, but have turned that to false (and deleted .bundle/config).
Where is this cache living (I'm on OSX, using RBenv and ruby 2.1.2), and how can I turn it off?
Have you tried running spring stop and restarting your server (assuming this is a Rails app)?
If it's referencing the file in the right place but executing the wrong code, that indicates that the old code is still loaded into memory. Often, this is because of the Spring pre-loader, which is used by default with Rails 4.1+.

How can I install a gem as if it was specified in a Gemfile?

I want to install a gem via gem install, but I need it to resolve with dependencies of the current project.
Basically I want the functionality that bundler gives me when I specify gem 'xyz' in a Gemfile, but I don't want to add that specific gem into the Gemfile.
I tried doing bundle exec gem install ... but it doesn't seem to work.
edit: The reason why I don't want to add it to the Gemfile is that it might be something like metric_fu, metrical, saikuro, rails_best_practices, etc. Simply gems that are kind of utility use and might only cluttler the project.
I might only want to use them temporarily, or install them, try out, if it doesn't work out the way I want do rvm gemset empty and bundle install again to clean up.
The point of Bundler is, in part, to prevent you from doing things like that (to prevent you from injecting gems from outside when your project doesn't declare them).
Looking for a way of doing that is looking for a bug in Bundler. If you did manage to find some way of skirting Bundler's enforcement mechanisms, you should probably not use it; instead, you may consider filing it as a bug with Bundler's issue tracker.
Now we come to the real questions: what can you do? and what should you do?
You should use either RVM gemsets or Bundler to isolate your application and its gem dependencies. You don't need both. I would recommend Bundler for this purpose over RVM gemsets.
You should add to your Gemfile any gems that you want to use and that integrate with your application (i.e., that either load your application or that are loaded as part of your application). This is not a requirement for any gems that refrain from integrating with your application.
You should refrain from committing a changed Gemfile or Gemfile.lock to version control until you are satisfied that your application continues to operate acceptably (tests pass, new gem does something useful, etc.).
Or you should stop using Bundler, because you want to do things it is explicitly designed to prevent you from doing (not recommended).
At the risk of sounding dumb, why not add it to the gemfile? You can always add it to its own group if you don't want to have to install it everywhere.
A slightly different approach is, if you're using version control, such as Git, to create a new branch and install the gems. If it doesn't work out, uninstall the gem (I'm not sure this will be done by bundle update on the old branch) and trash the branch. If it does, work, merge your stuff into the old the branch.
Though I do believe the other answers and comments have some very good points.

How does the OSGi framework set the Bundle ID?

I am trying to run OSGi framework (Equinox) in a main method.
Each time I start the framework, when I print BundleContext.getBundles().length, it says the framework has only 1 Bundle installed on (that is certainly the system bundle).
When I install my first bundle the bundle ID will continue from the last session. let's say if I had 4 bundles last session (and I have stopped and uninstalled all of them before stopping the system bundle), the first Bundle ID is set 5.
Now, I want to know how does the framework choose the bundle ID? Why and how does the framework remembers the last session, even though I had uninstalled all of the bundles? Is it because of Bundle Cache? And if it is, how can I clear the cache (to restart numbering from 1)?
The framework has the last used bundle id somewhere in the persistent store it manages. What this store looks like is a framework implementation detail. When you launch the framework, you can specify the org.osgi.framework.storage.clean framework configuration property. This will clear all installed bundles but I am not sure if it will reset the last used bundle id.
Deleting the equinox/org.eclipse.osgi folder resets the numbering. Before the delete make sure that your bundles don't have any important data under this folder.
The bundle command with a valid bundle id can show the absolute path of the equinox/org.eclipse.osgi folder:
osgi> bundle 7
slf4j.api_1.6.1 [7]
Id=7, Status=ACTIVE Data Root=D:\temp\test\equinox\org.eclipse.osgi\bundles\7\data
...
Here's what OSGI Core Release 8 specification says about bundle identifiers:
Bundle identifier - A long that is a Framework assigned unique
identifier for the full lifetime of a bundle, even if it is updated
or the Framework is restarted. Its purpose is to distinguish
bundles in a Framework. Bundle identifiers are assigned in
ascending order to bundles when they are installed. The method
getBundleId() returns a bundle's identifier.
So that at tells us two important properties about bundle identifiers: 1.) the relationship between bundleId and bundle is stable from the time that it is installed to the time that it is uninstalled, and 2.) that bundle identifiers are assign in ascending order to when they were installed.
Going back to the original question, trying to get bundles identifier number assignments to start over works against the OSGI specification for bundle identity, and you shouldn't mess around with trying to control bundle identity. For example, let's assume you have three bundles installed:
b1(0), b2(1), b3(2)
Now lets assume you uninstall bundle b2 (with id = 1):
b1(0),b3(2)
Now lets assume you re-install b2:
b1(0),b3(2),b2(3)
Notice that b2 gets a new id assigned to it. That id is stable for referencing b2 as long as b2 is not uninstalled. And if you notice, the id of 1 is no longer used. Bundle id is an identifier, not an index into an array. The bundleId of b3 can't be changed because it wasn't uninstalled, b2 could not be assigned the bundleId of 1, since that would violate the rule the bundle identifiers are assigned in ascending order to when they were installed (the OSGI framework doesn't remember that b2 was previously installed and uninstalled - it looks like its just being installed for the first time). Given that the bundleId is a long, that means we would need to do 9,223,372,036,854,775,807 bundle uninstalls before OSGI's bundle id number assignment scheme would run out of id's.

Resources