Is there any way to call code on the agent not as part of a build?

I'm writing a TeamCity plugin, and it'd be really useful if I could call a method on the agent-side part of my plugin from the server-side.

I realise that I could just add a new build configuration and then add it to the queue to essentially get this to happen, but obviously this won't work if the user is running professional edition and is already at the 20 build configuration limit.

Similarly, I could create a TCP listening socket during agent-side plugin startup and connect to it from the server-side plugin, but again, this obviously won't work if the user has configured a firewall to only allow TeamCity's TCP connection through and nothing else.

The best option I can think of so far, is to poll from the agent-side plugin to a server-side JSP, although obviously this incurs all the overheads of polling repeatedly.

I want a more robust way than the above if possible.

Thanks in advance!

3 comments
Comment actions Permalink

Could you provide some examples please.
What commands should the server send to the agents?

0
Comment actions Permalink

Sure, some background first: I work for a company that (amongst other things that aren't relevant here) writes and licenses command line applications.  I'm currently writing a TeamCity Build Runner Plugin to make it easier for users to use our existing command line applications, by giving them a nice UI to configure the command line parameters.  There's also the nice side effect that TeamCity will automatically update the agents with our agent-side plugin (and I'm using this to copy the command line application binaries onto the agents to make it ingeniously simple for users who now only need to install things once  on the TeamCity server).

I therefore need to license the command line applications so that when they are executed as part of a build they will work.  I imagine this being implemented as a Web UI Extension somewhere in the TeamCity UI that allows the user to enter their serial number.  On doing so, the server-side plugin needs to call to the agent-side plugin and give it the serial number.  It in turn, needs to run the command line application with some command line argument so that the command line application contacts our activation server to check that the serial number is valid, and then return an appropriate exit code.  The agent-side plugin then needs to report back to the server-side plugin what happened (this reason for working in this way is due to how our licensing works: currently it is written in C# and an activated license is tied to a specific machine, therefore the easiest solution is to have our agent-side plugin call the command line application with a particular command line argument to do the activation).

I didn't ask this in the original question, but I also need some way of restricting the build to only run on agents where the command line is licensed.  At the moment, because the command line application requires .NET Framework 2, I'm using:

@Override
    public List<Requirement> getRunnerSpecificRequirements(@NotNull Map<String, String> runParameters) {
        List<Requirement> ret = new ArrayList<Requirement>(super.getRunnerSpecificRequirements(runParameters));
        ret.add(new Requirement("DotNetFramework2.0_x86", "", RequirementType.EXISTS));
        return ret;
    }


I imagine I can add a suitable requirement for the command line being licensed on the agent, and then presumably the agent-side plugin can define an Agent Configuration Parameter, so that the requirement is satisifed iff the command line application is licensed on that agent.

0
Comment actions Permalink

David,

Thank you for the detials and sorry for the delayed answer.

If I understand your aim correctly, you need to pass something (a serial number?) from the server to the agent, then check the serial number on agent and make your runner compatible only with the agents which successfully check the number.

The second part (make only appropriate agents compatible) is usually handled via reporting a property in the agent plugin (which gets propagated to the server) and then adding a requirement much like you noted for DotNetFramework2.0_x86, but for your specific property.

As to the first part of transferring the data to the agent. You are right that one of the simpliest ways is to make the agent plugin poll your custom controller for the data. If the data will not change frequently, a poll request on agent start and then once in several minutes might do the trick.
I suppose you will still pass the same data with the build to be able to verify it during the build, so the delay introduced by periodic polling does not seem critical.

Another possible approach is to distribute the data from server to the agent inside agent plugin/tool. e.g. the server part can pack the serial number into a file and make TeamCity distribute the file to all the agents, where it can be found by the agent part.

BTW, can you share what kind of plugin you develop? Please let us know if you release it to public so that we update our plugins listing.

0

Please sign in to leave a comment.