Bamboo Plugin and Remote Agents

Hello everyone,

I have a quick question if any of you have any ideas about it. We do know when we develop a plugin for Atlassian Bamboo, if Bamboo has a remote agent it publishes that plugin to remote agent as well. This being said, it’s also said that remote agents are primitive versions of Atlassian Bamboo thus it doesn’t have all the libraries that Bamboo has. This is where my problem kicked in. If I briefly explain, we have developed a plugin for one of our customers. It’s working pretty well on Bamboo Local machine, however what i discovered yesterday is that the plugin is not working on remote agent (not even getting enabled) because of missing Active Objects artifacts on remote agent. Active Objects libraries are provided by Bamboo Local installation and it works well on Local agent machine. However it doesn’t exist on remote agent. The only library on remote agent is activeobjects-spi plugin. I have 2 questions regarding to this:

  1. As you can guess how can we solve this missing active objects plugin issue?
  2. How to deal with artifact (internal library) differences between remote agent and local Bamboo installation. Should I include those libraries in my artifact by manipulating the scope?
    Bamboo remote agent log says;
Cannot determine required plugins, cannot resolve bundle 'tr.com.obss.plugin.generic-bamboo-plugin'
2018-12-07 10:04:18,973 ERROR [remoteEventRebroadcasterMessageListenerContainer-1] [OsgiPlugin] Detected an error (BundleException) enabling the plugin 'tr.com.obss.plugin.generic-bamboo-plugin' : Unresolved constraint in bundle tr.com.obss.plugin.generic-bamboo-plugin [48]: Unable to resolve 48.0: missing requirement [48.0] osgi.wiring.package; (osgi.wiring.package=com.atlassian.activeobjects.external).  This error usually occurs when your plugin imports a package from another bundle with a specific version constraint and either the bundle providing that package doesn't meet those version constraints, or there is no bundle available that provides the specified package. For more details on how to fix this, see https://developer.atlassian.com/x/mQAN

Plugin-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:atlassian-scanner="http://www.atlassian.com/schema/atlassian-scanner/2"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.atlassian.com/schema/atlassian-scanner/2
        http://www.atlassian.com/schema/atlassian-scanner/2/atlassian-scanner.xsd">
	<atlassian-scanner:scan-indexes />
</beans>

Pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

	<modelVersion>4.0.0</modelVersion>
	<groupId>tr.com.obss.plugin</groupId>
	<artifactId>generic-bamboo-plugin</artifactId>
	<version>0.4.18</version>

	<organization>
		<name>Open Business Software Solutions</name>
		<url>http://obss.co/</url>
	</organization>

	<name>Misc Tools for Atlassian Bamboo</name>
	<description>This is a utiliy tool for Atlassian Bamboo developed by OBSS.</description>
	<packaging>atlassian-plugin</packaging>

	<properties>
		<bamboo.version>6.6.2</bamboo.version>
		<bamboo.data.version>6.6.2</bamboo.data.version>
		<amps.version>6.3.15</amps.version>
		<plugin.testrunner.version>1.2.3</plugin.testrunner.version>
		<atlassian.spring.scanner.version>2.1.7</atlassian.spring.scanner.version>
		<!-- This key is used to keep the consistency between the key in atlassian-plugin.xml 
			and the key to generate bundle. -->
		<atlassian.plugin.key>${project.groupId}.${project.artifactId}</atlassian.plugin.key>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
	</properties>

	<dependencies>
		<dependency>
			<groupId>com.atlassian.bamboo</groupId>
			<artifactId>atlassian-bamboo-web</artifactId>
			<version>${bamboo.version}</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.6.6</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>com.atlassian.plugin</groupId>
			<artifactId>atlassian-spring-scanner-annotation</artifactId>
			<version>${atlassian.spring.scanner.version}</version>
			<scope>provided</scope>
		</dependency>

		<!-- <dependency> -->
		<!-- <groupId>com.atlassian.plugin</groupId> -->
		<!-- <artifactId>atlassian-spring-scanner-runtime</artifactId> -->
		<!-- <version>${atlassian.spring.scanner.version}</version> -->
		<!-- <scope>runtime</scope> -->
		<!-- </dependency> -->

		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
			<scope>test</scope>
		</dependency>

		<!-- WIRED TEST RUNNER DEPENDENCIES -->
		<dependency>
			<groupId>com.atlassian.plugins</groupId>
			<artifactId>atlassian-plugins-osgi-testrunner</artifactId>
			<version>${plugin.testrunner.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>javax.ws.rs</groupId>
			<artifactId>jsr311-api</artifactId>
			<version>1.1.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>com.google.code.gson</groupId>
			<artifactId>gson</artifactId>
			<version>2.2.2-atlassian-1</version>
		</dependency>
		<dependency>
			<groupId>com.atlassian.applinks</groupId>
			<artifactId>applinks-api</artifactId>
			<version>5.0.3</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>com.atlassian.sal</groupId>
			<artifactId>sal-api</artifactId>
			<version>3.0.7</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>com.atlassian.activeobjects</groupId>
			<artifactId>activeobjects-plugin</artifactId>
			<version>1.2.3</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>com.atlassian.maven.plugins</groupId>
				<artifactId>maven-bamboo-plugin</artifactId>
				<version>${amps.version}</version>
				<extensions>true</extensions>
				<configuration>
					<productVersion>${bamboo.version}</productVersion>
					<productDataVersion>${bamboo.data.version}</productDataVersion>
					<enableQuickReload>true</enableQuickReload>
					<enableFastdev>true</enableFastdev>
					<productDataPath>${basedir}/src/generated-test-resources.zip</productDataPath>

					<!-- https://developer.atlassian.com/docs/advanced-topics/configuration-of-instructions-in-atlassian-plugins -->
					<instructions>
						<Atlassian-Plugin-Key>${atlassian.plugin.key}</Atlassian-Plugin-Key>

						<Import-Package>
							*
						</Import-Package>
						<Spring-Context>*</Spring-Context>
					</instructions>
					<skipManifestValidation>true</skipManifestValidation>
				</configuration>
			</plugin>

			<plugin>
				<groupId>com.atlassian.plugin</groupId>
				<artifactId>atlassian-spring-scanner-maven-plugin</artifactId>
				<version>${atlassian.spring.scanner.version}</version>
				<executions>
					<execution>
						<goals>
							<goal>atlassian-spring-scanner</goal>
						</goals>
						<phase>process-classes</phase>
					</execution>
				</executions>
				<configuration>
					<scannedDependencies>
						<dependency>
							<groupId>com.atlassian.plugin</groupId>
							<artifactId>atlassian-spring-scanner-external-jar</artifactId>
						</dependency>
					</scannedDependencies>
					<verbose>false</verbose>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Thanks in advance,
Regards,
Korkut.

Hi Korkut

Even if you managed to bundle the Active Objects library into your plugin and are able to access it, you won’t be able to store data in the database. The remote agents don’t have direct access to the data and depend on performing limited processing locally and send the processed data back to the central server.

We made Active Objects access work for us by getting our task to add a JSON blob of data to the task build result (It’s a map data structure) and then implement a Build Processor Server Module to read the data from the task result and then store it in the database.

How we store data on the result within our task

        final TaskResult taskResult = taskResultBuilder.checkTestFailures().build();
        try {
            String value = mapper.writeValueAsString(reports);
            taskResult.getResultData().put("UNIQUE_KEY", value);
        } catch (JsonProcessingException e) { }

It’s worth noting due to dependency conflicts (The limited availability of libs on the agent) you will likely have to separate plugins into two (one for the agent and the other for the server) using maven sub-modules and bundle them together as a single OBR using OSGI.

I believe there are other ways to do the server to remote agents communication but the documentation is so bad I couldn’t get them to work in all deployment configurations.

Cheers
Alan

Hi @alan.parkinson,

Thanks for your sound answer first of all. If you can allow me, I want to briefly explain what I am trying to achieve. We’ve implemented a quartz scheduler that makes DB level connections to external DB via JNDI. It works every midnight and injects plan variables to the plans if they don’t have any or updates variables if any of them changed. Everything is working fine till here. However, one another module has to log these connections and updates for security and performance measuring purposes on a AO table. In the end, what we wanna achieve is this. I have no intention to access Active Objects through remote agents of course. However, although the plugin works on local Bamboo instance, it has to work on both local and remote machines even remote agent doesn’t have anything to do because plugin also has tasks and post build actions that need to work on remote agent.
What is logical in here seems like as you mentioned creating an obr and isolate active object plugin from the tasks and bundle them as obr. Even the Active Object Plugin module can’t be initialized on remote agent at least I will have the other plugin for tasks and build processors.
I couldn’t come any other idea than this either. What do you think?
Ah one more thing before i forget. Do you have any idea how can we implement this? An article or example maybe?

Regards,
Korkut.

Hi @korkut.kose

Unfortunately Bamboo documentation is missing quite a bit of information, and the best source of information is to look at the source code of Atlassian’s own bamboo plugins on Bitbucket, but they seem to be removing these over the last 12 months.

Have you consider injecting your variable before the build execution moves to the remote agent? e.g. moving your code execution further up the chain. The Pre-Build Queued Action or a similar module might be the place to look.

It’s old but this 2012 talk on Bamboo has some useful information Developing for Remote Bamboo Agents, AtlasCamp US 2012

Cheers
Alan

1 Like