Using the CloudBees CD Perl API

You can use the CloudBees CD Perl API for the following operations:

  • Model and deploy applications

  • Create and manage resources

  • Create environment models and add resources to them

  • Model and run pipelines

  • Model and run releases

  • Create and call procedures

  • Create and manage artifacts

  • Create and manage object properties

The Perl API can be used from a command-line interface, in a shell script, or in a batch file. It supports ectool and ec-perl commands:

  • ectool is a command-line tool developed to script CloudBees CD operations.

  • ec-perl is delivered as a Perl package during CloudBees CD installation, or you can use any Perl of your choice.

This topic describes ectool and ec-perl usage and their differences, because they can work together.

Using ectool

ectool is a command-line application that provides operational control over the CloudBees CD system. It supports a large collection of commands, each of which translates to a message sent to the CloudBees CD server. For example, ectool getProjects returns information about all projects defined on the server.

  • ectool --help displays a summary of all commands and other command-line options.

  • ectool --help <command> returns information about <command>, For example, ectool --help modifyStep returns information about the modifyStep command.

Signing in

If you use ectool outside of a job, you must invoke the ectool login command to sign in to the CloudBees CD server. After signing in, ectool saves information about the login session for use in future ectool invocations. If you run ectool as part of a CloudBees CD job, you do not need to sign in; ectool uses the login session (and credentials) for that job.

To log in to a specific server, see the example below, which includes the server name, user name, and password.

ectool --server bldg1server login "Ellen Ernst" "ee123"

General syntax for ectool command usage:

ectool [global argument]   [named arguments]

Global Arguments (Optional)

See Common Global Options for more information.

Character Restrictions in Arguments

ectool does not support any argument value that begins with a -- (double hyphen), because this is reserved as the prefix for argument names.

Passing Lists as Arguments

Some API commands include arguments that expect a list of values in one of two list forms: value lists and name/value pairs. The syntax to specify a list depends on whether you are using ectool or ec-perl.

For ectool

  • value list: each value is specified as a separate argument on the command line.

    Example:

    ectool addUsersToGroup group1 --userNames user1 user2 user3
  • name/value pairs: each pair is specified as a separate argument in the form name=value.

    Example:

    ectool runProcedure proj1 --procedureName proc1 --actualParameter parm1=value1 parm2=value2

For ec-perl

  • value list: the argument value is a reference to an array of values.

    Example:

    $cmdr->addUsersToGroup({ groupName => group1,                          userName => ['user1', 'user2']});
  • name/value pairs: the argument value is a reference to an array of hash references. Each hash contains a pair of entries, one for the name and one for the value. The hash keys depend on the specific API.

    Example:

    $cmdr->runProcedure({ projectName   => 'proj1',
                          procedureName => 'proc1',
                          actualParameter => [ { actualParameterName => 'parm1',
                                                value => 'value1'},
                                               { actualParameterName => 'parm2',
                                                value => 'value2'}
    										 ]
    					 });

Using ec-perl

When a CloudBees CD component is installed—server, agent, or tools (using the express or advanced installation type)—a copy of Perl is installed. This copy is pre-configured with all the packages you need to run the CloudBees CD Perl API. CloudBees CD does not, however, automatically add this version of Perl to your path because:

  • The CloudBees CD installation must not interfere with existing scripts, which depend on finding another copy of Perl you already use.

  • Special environment variables need to be set before calling Perl.

Both of these issues are addressed with a small wrapper program called ec-perl. The wrapper is installed as part of CloudBees CD, and it is in a directory that is added to your path. When the ec-perl wrapper runs, it sets up the environment, finds, and calls the CloudBees CD copy of Perl, passing all of its parameters to Perl.

To run ec-perl from a command line (or in a CloudBees CD step) enter:

ec-perl yourPerlOptions yourPerlScript.pl

The Perl script can include API calls to CloudBees CD with no other special handling required.

For a CloudBees CD step, you can enter the Perl script directly into the "Command" field, and set the "Shell" field to ec-perl. The CloudBees CD -installed Perl is used to process the Perl script.

You can develop Perl scripts to access the Perl API directly. Because ectool uses the Perl API to execute its commands, any ectool command you can execute can be executed using the Perl API. If you are writing (or currently using) a script that makes tens or hundreds of calls, the Perl API provides a significant performance improvement over ectool.

The Perl API is delivered as a collection of Perl packages pre-installed in a Perl 5.8 distribution. The main API package is called ElectricCommander.

Perl API structure

The Perl API has the same four elements as ectool, but the way these elements are specified is quite different.

Specifying global options

To use the CloudBees CD Perl API, you must first create an object. Global arguments are specified at the time the object is created. These arguments are passed as members of an anonymous hash reference, as shown in the following example:

use ElectricCommander;
$cmdr = ElectricCommander->new({
    server      =>  "vm-xpsp2",
    port        =>  "8000",
    securePort  =>  "8443",
    debug       =>  "1"
});

In the example above, port options are not really necessary because they specify default values. When you want to specify the server name only, you can use the shorthand form:

use ElectricCommander;
$cmdr = ElectricCommander->new("vm-xpsp2");

An even simpler form can be used if you call the Perl API from a script running as part of a CloudBees CD job step. In this case, the CloudBees CD package sets the server name based on the environment variable, COMMANDER_SERVER, set by the CloudBees CD agent.

use ElectricCommander;
$cmdr = ElectricCommander->new();

To see a complete list of global commands you can use with Perl, click here.

If your script uses international characters (non-ASCII), add the following block to the top of your ec-perl command block:

use utf8;
ElectricCommander::initEncodings();

Specifying subcommands

For each subcommand, there is a corresponding CloudBees CD object function.

For example, to retrieve a list of jobs, use

$cmdr->getJobs();

Specifying arguments

Most subcommands expect one or more arguments. Arguments are specified as key value pairs in a hash ref passed as the final argument to the subcommand. Additionally, as a convenience, some arguments may be specified as positional arguments prior to the options hash ref.

For example, setProperty has two positional arguments, propertyName and value, and an optional jobId argument that can be specified in either of the following forms:

$cmdr->setProperty("/projects/test/buildNumber", "22",
    {jobId => $jobId}
);

or

$cmdr->setProperty({
     propertyName => "/projects/test/buildNumber",
     value => "22",
     jobId => $jobId
});

Handling return values

Every function for the requested object returns an object of type XML::XPath. This is an object that returns a parsed representation of the CloudBees CD returned XML block. See documentation on CPAN for more information.

$xPath = $cmdr\->setProperty("filename", "temp.xml");
print "Return data from Commander:\n".
$xPath->findnodes_as_string ("/") . "\n";

Error handling

If a function call to the CloudBees CD object encounters an error, by default, it dies inside Perl and prints an error message. If you want to handle errors yourself and continue processing, you must set a flag to disable internal error handling and handle the error in your code. For example:

$cmdr->abortOnError(0);
$xPath = $cmdr\->getResource("NonExistent Resource");
if ($xPath) {
     my $code = $xPath->findvalue('//code')->value();
     if ($code ne "") {
          my $mesg = $xPath->findvalue('//message');
          print "Returned code is '$code'\n$mesg\n";
          exit 1;
     }
}

An alternative to using the abortOnError flag:

eval {$cmdr\->get...};
if ($@) {
print "bad stuff: $@";
exit 1;
}

Specifying a named object

Any API argument that refers to a named object (for example, projectName or procedureName) performs property reference expansion before looking in the database for the object. This process allows constructs like the following to work without making two separate server requests:

$cmdr->getProject ('$[/server/defaultProject]')

Property reference expansion for names occurs in the global context, so context-relative shortcuts like "myProject" are not available.

Common global options

Global arguments can be used alone or in conjunction with other commands. These arguments are used to control communication with the server and can be used with the ectool or ec-perl APIs.

Global Arguments Description

--help

Display an online version of ectool commands with a short description. Display command information if followed by a command name.

--version

Display the ectool version number.

--server <hostname>

The CloudBees CD server address. Default is the COMMANDER_SERVER environment variable. If this variable does not exist, the default falls to the last server contacted through the API. However, if there is no record for which server was contacted, the default is to localhost.

If you are using multiple servers, use the server option to ensure the correct server is specified for your task. For example, if you are using the import command, the server option may be particularly important.

Do not use in a step context: steps running ectool or Perl scripts should never provide the server option if the intention is to communicate with the server that launched the step. If the intention is to communicate with a different server, this agent must be a registered, enabled resource in the second server. Thus, that server will ping the agent, and the agent will learn how to communicate with that server.

In a step context, the Perl API proxy server requests through the step’s agent. If the agent does not recognize the provided server-name, it rejects the request. ectool and Perl API retry the operation because at some point the server should ping the agent, and then the agent will have learned how to communicate with the server.

Generally, the issue is that the server publicizes its name as a fully-qualified domain name and the Perl API issues requests with a simple-name for the server. This can happen if the step explicitly states which server it is connecting to. Fix your steps that invoke ectool so it no longer includes the server-name, and ectool defaults to the server-name that the server provided.

--port <port>

HTTP listener port on the CloudBees CD server. Defaults to port 8000.

--securePort <secureport>

HTTPS listener port on the CloudBees CD server. Defaults to port 8443.

--secure <0|1>

Use HTTPS to communicate with the CloudBees CD server. Defaults to 1.

Certain requests (for example, login, createUser, and modifyUser ) automatically use HTTPS because passwords are being sent, which means it is not necessary to specify secure for those APIs.

--timeout <s>

An API call waits for a response from the server for a specified amount of time. Timeout for server communication defaults to 180 seconds (3 minutes) if no other time is specified. After the timeout, the API call stops waiting for a response, but the server continues to process the command.

You can also use the global CloudBees CD COMMANDER_ECTOOL_TIMEOUT environment variable. The --timeout <s> argument overrides the value of this environment variable if it is set.

--retryTimeout <s>

This is a separate timer, independent of the retry flag, and is used to control CloudBees CD automatic error recovery. When the API cannot contact the CloudBees CD server, it keeps trying to contact the server for this length of time. When the API is called from inside a step, it defaults to 24 hours.

You can also use the global CloudBees CD COMMANDER_ECTOOL_RETRY_TIMEOUT environment variable. The --retryTimeout <s> argument overrides the value of this environment variable if it is set.

--retry <0|1>

Retry the request if it times out based on the "timeout" value. Default is "0" and should be changed rarely.

--user <username>

Use the session associated with the user. Defaults to the user who last logged in.

--service <spn>

Specify the service principal name to use for Kerberos. Defaults to HTTP@host.domain.

--setDefault <0|1>

Use the current session as the default for subsequent invocations. Defaults to 1.

encoding <charEncoding>

Use the specified encoding for input/output. For example, for charEncoding, enter UTF-8, cp 437, and so on. Default is autodetected.

--dryrun

Displays session information and the request that would be sent, without communicating with the server. If a subcommand is specified, the server request that would be sent is displayed. This option can also be used to change the default user/server value by specifying the --user or --server options.

--silent

Suppresses printing the result. For example: ectool --silent createResource foo will not print the resource name, agent state, any modify information, create time, owner, port, or any other information otherwise displayed when you create a resource.

--valueOf

This option can return the value of a unique element. Because many ectool APIs return an XML result, it is inconvenient to use ectool in shell scripts and makefiles where you might want a piece of the ectool result to incorporate into some other logic. Using the --valueOf <path> option evaluates the XML result and emits the value of that node to satisfy such use cases. For example: $ ectool --valueOf '//version' getServerStatus returns only "4.1.0.48418".

--format <format>

Specifies the response format. Must be one of 'xml' or 'json'. Defaults to 'xml'. For example, you might specify: ectool --format json setProperty summary hello

--ignoreEnvironment

Force ectool to ignore COMMANDER_ENV variables.

The batch API

The Perl API supports a batch operation mode that allows you to send multiple API requests in a single envelope, which has several advantages over standard, individual API calls in some situations. For example, you could use the batch API when you need to set multiple property values.

Using the batch API

To use the batch API, first create an instance of ElectricCommander as you would for a standard API. From your newly created instance, create a batch object using the newBatch method.

Example—creating a batch object:

  use ElectricCommander;
  my $ec = new ElectricCommander();
  # Create the batch API object
  my $batch = $ec->newBatch();

The batch object supports all the same calls as the standard API. The result of each call is a numeric requestId that can be used to locate a response from an individual request within the batch.

Example—creating multiple requests in a batch:

  # Create multiple requests
  my @reqIds = (
    $batch->setProperty("/myJob/p1", 99),
    $batch->incrementProperty("/myJob/p2")
  );

After the batch is created, submit it to the server for processing. The return from the submit() call is an XPath object that represents an XML document containing the responses for all of the API requests.

Example—submitting the batch:

# Submit all the requests in a single envelope
$batch->submit();

Sample response from this example:


 	
  	199827
   	p1
   	2010-07-21T16:41:20.003Z
   	1
   	project: EA Articles
   	2010-07-21T16:41:20.003Z
   	project: EA Articles
   	99
    
  
  
    
      199828
      p2
      2010-07-21T16:41:20.019Z
      1
      project: EA Articles
      2010-07-21T16:41:20.019Z
      project: EA Articles
      1
    
  

To extract information from the response to a request, use standard XPath syntax, and enter the requestId returned by that specific API call to either find or findvalue functions on the batch object.

Example—extracting response information:

# Extract the value from the "increment" request
my $value = $batch->findvalue($reqIds[0], 'property/value');
print "New value is $value\n";

By default, the server processes each request in the envelope serially, each in its own transaction. But as an optimization, if all the requests in the envelope are read-only requests, such as getProperty API requests, then the server handles the requests in parallel, each request in its own transaction. The newBatch method has an optional argument to request the processor mode that can be used to tell the server how to process multiple requests, overriding the server’s default behavior. There are three request processor modes:

  • serial: each request in the envelope is processed serially, each in its own transaction. This is the default mode when one or more requests in the envelope are update requests or requests that can affect a change in the system.

  • parallel: each request in the envelope is processed in parallel, each in its own transaction. This is the default mode when all the requests in the envelope are read-only requests.

  • single: each request in the envelope is processed serially, all in the same transaction. The difference between single and serial mode is that in a single mode, since all requests are processed in the same transaction, then in case of an error, all the requests will be rolled back by default. Another key difference is that all locks acquired by the requests are held for the duration of the transaction while all the requests are being processed. This can increase contention in the system, including the database when other requests that are not part of the batch need access to the same objects locked by the batch API. So use the single mode only when needed and the likelihood of contention is not high.

Single-transaction batch processing can continue after errors if you enter an ignoreErrors attribute in the request,requests, or both elements. The ignoreErrors value is evaluated as a regular expression against any error codes from the batch. If the expression matches, an error does not cause the batch to fail.

There are two ways to specify ignoreErrors when issuing a single-transaction batch call:

  • Specify the ignoreErrors attribute when creating the batch object. In this case, the attribute applies to all requests in the batch:

    my $batch = $N->newBatch('single', 'DuplicateResourceName');
  • Specify the ignoreErrors attribute as an argument to an individual request. In this case, the attribute applies only to that request and will override any global value specified:

    my $req2 = $batch->createResource($resource, {ignoreErrors => 'DuplicateResourceName'});

Using your existing Perl distribution

You may want to use your existing Perl distribution. If so, CloudBees CD uses a CPAN style module, located in <installdir>/src, that can be installed with the following commands:

tar xzvf ElectricCommander-.tar.gzcd ElectricCommander-perl Makefile.PLmake install;
# Use nmake on Windows

These commands install the CloudBees CD Perl and all of its submodules. If some prerequisite modules are missing, the Makefile.PL script will indicate which modules are needed.

Expanding the CloudBees CD Perl Distribution

You may want expand the CloudBees CD Perl distribution by adding Perl modules from CPAN or third party vendors.

Install Perl modules using the CPAN installer. The installer comes with the CloudBees CD Perl distribution in <CloudBees_Flow_Dir>/perl/bin.

During a CloudBees CD upgrade, the installer makes every attempt to preserve Perl packages. However, future CloudBees CD versions may contain an upgraded Perl version, which may then require a reinstall of any added Perl packages.

Linux:

From the command line use: <CloudBees_Flow_Dir>/perl/bin/perl -MCPAN -e 'install <module>'

Windows:

Compatibility with CloudBees CD is important. CloudBees CD 5.0 and later use Perl 5.8 for ec-perl.

If the Perl package is not Perl-only and requires compiling (for example, for C code):

  • Use Windows Visual Studio VC6 (the same version used by CloudBees CD ).

  • Make sure that cl and nmake are both in your path. The Visual Studio install has a Command Prompt with these executables already in the path.

Extra steps are needed for Windows because of a problem with Perl and CPAN if you are running from a directory with spaces in the name. (By default, CloudBees CD has spaces in the installed directory.)

  • Use a network drive to eliminate references to spaces.

    1. Use subst to mount the Perl directory under a different drive letter: c:\> subst x: "c:\program files\Electric Cloud\ElectricCommander"

    2. Start CPAN from the new location: c:\> x:\perl\bin\perl -MCPAN -e shell

    3. Configure CPAN to install into the new location: cpan> o conf makepl_arg PREFIX=x:/perl

    4. Install the module: cpan> install <module> Ending CPAN: ` cpan> quit`

  • Change the <CloudBees CD _Dir>\perl\lib\config.pm file to eliminate spaces in references to the CloudBees CD path. For example:

#archlibexp => 'C:\Program Files\\Electric Cloud\ElectricCommander\perl\lib',
  archlibexp => 'X:\perl\lib',
#privlibexp => 'C:\Program Files\\Electric Cloud\ElectricCommander\perl\lib',
  privlibexp => 'X:\perl\lib',
#scriptdir => 'C:\Program Files\\Electric Cloud\ElectricCommander\perl\lib',
  scriptdir => 'X:\perl\lib',
#sitearchexp => 'C:\Program Files\\Electric Cloud\ElectricCommander\perl\site\lib',
  sitearchexp => 'X:\perl\lib',
#sitelibexp => 'C:\Program Files\\Electric Cloud\ElectricCommander\perl\site\lib',
  sitelibexp => 'X:\perl\lib',
  • Temporarily add X:\perl\bin to your Windows path.

Using Perl API Commands in Javascript

You can use CloudBees CD Perl API commands in Javascript. In previous releases, Javascript was read-only, and only getProperty and setProperty were called in Javascript.

These are examples of how to use Perl API commands in Javascript:

  • To create a project:

    ectool evalScript --value "(api.createProject(
        { 'projectName':'alex34' } )).project.projectName ; " alex34
  • To return the object type, use this Javascript script:

    ectool evalScript --value "api.getResources({})" [object Object]
  • For a parsed object, use the "JSON.stringify()" call:

    ectool evalScript --value "JSON.stringify(api.getResources({})) "{
       "resource":{
          "resourceId":"ceecfce5-2d0d-11e4-8888-005056330afe",
          "resourceName":"local",
          "agentState":{
             "alive":"1",
             "details":"The agent is alive",
             "hostOS":"Linux qa-ub1210-64-2 3.5.0-19-generic
                       #30-Ubuntu SMP Tue Nov 13 17:48:01 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux",
             "hostPlatform":"linux",
             "message":"The agent is alive",
             "pingToken":"1409049660",
             "protocolVersion":"6",
             "state":"alive",
             "time":"2014-08-26T10:43:25.802Z",
             "version":"5.0.3.76444"
          },
          "createTime":"2014-08-26T10:43:25.617Z",
          "description":"Local resource created during installation.",
          "hostName":"qa-ub1210-64-2.electric-cloud.com",
          "hostOS":"Linux qa-ub1210-64-2 3.5.0-19-generic
                    #30-Ubuntu SMP Tue Nov 13 17:48:01 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux",
          "hostPlatform":"linux",
          "lastModifiedBy":"project: zebra",
          "lastRunTime":"2014-08-26T10:50:23.786Z",
          "modifyTime":"2014-08-26T10:50:23.786Z",
          "owner":"admin",
          "port":"7800",
          "proxyPort":"",
          "resourceAgentState":"alive",
          "resourceAgentVersion":"5.0.3.76444",
          "resourceDisabled":"0",
          "stepCount":"0",
          "stepLimit":"",
          "trusted":"0",
          "useSSL":"1",
          "propertySheetId":"ceee8387-2d0d-11e4-8888-005056330afe",
          "zoneName":"default",
          "pools":"default"
       }
    }
  • To retrieve the first resourceName:

    ectool evalScript --value "api.getResources({}).resource[0].resourceName"