[SOLVED] Do Bamboo remote agents have access to PluginLicenseManager?

Hi,

I would like to use PluginLicenceManager inside a Bamboo task so that I can print out a please licence message rather then just having the plugin be disabled completely. Is this possible?

I’m using Bamboo 6.9.1 configured with Spring Scanner 2 and UPM

The task works fine on the server’s built-in agent but remote agents fail to load the plugin:

 Caused by: org.osgi.framework.BundleException: Unresolved constraint in bundle com.declarativesystems.bamboo.puppetdeploy [38]: Unable to resolve 38.0: missing requirement [38.0] osgi.wiring.package; (osgi.wiring.package=com.atlassian.upm.api.license)

Looking at some of the forum posts[1], I tried adding:

<Import-Package>
  com.atlassian.upm.*;resolution:="optional",
</Import-Package>

All this does though is mark the bean as optional during scanning. When my task is instantiated I see the error:

bamboo java.lang.NoClassDefFoundError: com/atlassian/upm/api/license/PluginLicenseManager

Which makes me think PluginLicenseManager.class file is simply not available on a remote agent.

What are other plugin authors doing to get around this? Does anyone have a way figured out to access plugin license status from a Task when running remotely? I’m almost certain that trying to force bundling of UPM inside my plugin by removing <scope>provided</scope> is a bad idea ™, is anyone able to confirm this?

Thanks,
Geoff

My guess is that the PluginLicenseManager isn’t available on the agent (there isn’t a backing db for it to query for the licenses). You’ll need to look at something like the pre-build module (forgive me - my Bamboo skills are slightly rusty - I believe that there is a better module). https://www.go2group.com/blog/sharing-information-from-bamboo-server-to-bamboo-remote-agent/ has a write up on how to use the prebuild.

2 Likes

Yeah that would make total sense, thanks Daniel.

In the end I decided to go the easy route and just disable the plugin completely by adding a LicenseChecker class[1]… Now the plugin works fully but of course the license check events don’t seem to fire :face_with_symbols_over_mouth:.

[1] https://bitbucket.org/atlassian/tutorial-plugin-licensing-api/src/01026f0ea9c7eeba53c8e01ba6254bf3b2be6c54/tutorial-plugin-licensing-api/src/main/java/com/example/plugins/tutorial/licensing/LicenseChecker.java

I think its safe to say at this point, the answer is: no, the class is not available.

Daniel, thanks heaps for your suggestion about using a Pre-Build Queued Action and using the build context to pass data. This is totally the way to go for this kind of thing - I have it working!

The CheckLicense class I linked to earlier is so old it doesn’t even compile any more. I hacked around with it and long story short most of the events that I’d be interested in catching like PluginLicenseExpiredEvent are never thrown in the first place. It seems like functionality has been reduced to just the bare miniumum so that plugin upgrades etc can be handled nicely.

Just incase anyone else needs to pass data like this in the future, here’s how you do it:

  1. Create a class implementing CustomPreBuildQueuedAction and inject PluginLicenceManager
  2. Add a preBuildQueuedAction stanza to atlassian-plugin.xml (see example above)
  3. In the public BuildContext call() method of your new class, add the license lookup and save the result as custom build data:
    public BuildContext call() throws InterruptedException, Exception {
        String license;
        if (!pluginLicenseManager.getLicense().isDefined() ||
                pluginLicenseManager.getLicense().get().getError().isDefined()) {
            license = "ERROR";
        } else {
            license = "OK ... you rock!";
        }

        // from https://community.atlassian.com/t5/Answers-Developer-Questions/How-to-share-data-between-Bamboo-and-Bamboo-remote-agent-from-a/qaq-p/564124
        buildContext.getBuildResult().getCustomBuildData().put("server", "test3");
        buildContext.getBuildResult().getCustomBuildData().put("license", license);
        return buildContext;
    }
  1. In your Task, you can look the data up:
        // licence check
        buildLogger.addErrorLogEntry("GOT THIS " + taskContext.getBuildContext().getBuildResult().getCustomBuildData().get("server"));
        buildLogger.addErrorLogEntry("GOT THIS " + taskContext.getBuildContext().getBuildResult().getCustomBuildData().get("license"));
  1. Final things to do to stop plugin failing to load on remote agents:

    • Beans that should only be on the server (like this one) get annotated @BambooComponent and @BambooImport for injected beans.
    • Make sure you optional the UPM dependencies!
    <Import-Package>
        com.atlassian.upm.*;resolution:="optional",
        *
    </Import-Package>

:beers:

1 Like

To briefly chime in here - the ‘better module’ @danielwester has been referring to is the RuntimeTaskDataProvider, which provides server side pre-build and post-build actions that “may be implemented by task” to pass custom data to and from remote agents.

While it’s oddly marked as “@ExperimentalApi” still (only just noticed), it’s what the Atlassian team meanwhile recommends for this purpose, and what we (Utoolity) and I think most other Bamboo app vendors use these days.

3 Likes

awesome, thanks for info!