IBM DevOps Deploy (IBM UrbanCode Deploy) Custom Plugin Development

IBM DevOps Deploy (IBM UrbanCode Deploy) Custom Plugin Development

ยท

10 min read

IBM UrbanCode Deploy, also known as IBM DevOps Deploy, is a powerful tool for automating application deployments across various environments. It comes with an extensive range of built-in plugins, but many organizations find the need to develop custom plugins to meet their specific deployment requirements.

I am going to guide you through an end-to-end build of a custom IBM UCD plugin from the setup phase through deployment. During this time, we'll share best practices with you that would ensure integration as smooth as silk and optimization for your best plugin performance.


Why Develop Custom Plugins for IBM UrbanCode Deploy?

Custom plugins can extend IBM UCD beyond its default capabilities. Examples of use cases include integration with third-party tools, automating complex deployment tasks that have organisation-specific logic, and enforcing security compliance by making custom deployment policies.


Prerequisites for Custom Plugin Development

Before diving into development, ensure you have:

  • IBM UrbanCode Deploy installed (or access to a UCD server for testing).

  • Java Development Kit (JDK 8 or later).

  • Apache Maven for building the plugin.

  • A code editor or IDE (e.g., IntelliJ IDEA, Eclipse, or VS Code).

  • Familiarity with XML and Java.


Steps to Develop a Custom IBM UCD Plugin

๐’๐ญ๐ž๐ฉ ๐Ÿ: ๐’๐ž๐ญ ๐”๐ฉ ๐˜๐จ๐ฎ๐ซ ๐ƒ๐ž๐ฏ๐ž๐ฅ๐จ๐ฉ๐ฆ๐ž๐ง๐ญ ๐„๐ง๐ฏ๐ข๐ซ๐จ๐ง๐ฆ๐ž๐ง๐ญ

  • Download the IBM UCD Plugin Development Kit (PDK) from the GitHub repository Download Custom PDK.

  • After downloading, extract the PDK and open the extracted directory in your preferred code editor. For this example, Iโ€™ll be using Visual Studio Code.
    Project Structure

      Custom-Plugin-Agent-Data-Parser/
      โ”‚
      โ”œโ”€โ”€ pom.xml
      โ”‚
      โ””โ”€โ”€ src/
          โ””โ”€โ”€ main/
              โ””โ”€โ”€ java/
                  โ””โ”€โ”€ com/
                      โ””โ”€โ”€ opensource/
                          โ””โ”€โ”€ GetAgentDetailsCustom.java
    

    UCD Plugin Structure

      Custom-Plugin-Agent-Data-Parser/
          โ”œโ”€โ”€ <maven-built>.jar
          โ”œโ”€โ”€ plugin.xml
          โ”œโ”€โ”€ info.xml
          โ””โ”€โ”€ upgrade.xml
    

๐’๐ญ๐ž๐ฉ ๐Ÿ: ๐ƒ๐ž๐Ÿ๐ข๐ง๐ž ๐ญ๐ก๐ž ๐ฉ๐ฅ๐ฎ๐ ๐ข๐ง'๐ฌ ๐Ÿ๐ฎ๐ง๐œ๐ญ๐ข๐จ๐ง๐š๐ฅ๐ข๐ญ๐ฒ, ๐ข๐๐ž๐ง๐ญ๐ข๐Ÿ๐ฒ ๐ซ๐ž๐ช๐ฎ๐ข๐ซ๐ž๐ ๐ข๐ง๐ฉ๐ฎ๐ญ๐ฌ, ๐š๐ง๐ ๐๐ž๐ฌ๐ข๐ ๐ง ๐ญ๐ก๐ž ๐ฉ๐ฅ๐ฎ๐ ๐ข๐ง.๐ฑ๐ฆ๐ฅ ๐œ๐จ๐ง๐Ÿ๐ข๐ ๐ฎ๐ซ๐š๐ญ๐ข๐จ๐ง.

plugin.xml It helps define essential information regarding the plugin, including its name and version, and also the actions that the plugin should carry out; it will also configure the plugin's dependencies and set the execution order of its steps here.

  1. Identifying the Required Inputs and drafting a preliminary blueprint.

    • For our IBM UCD Agent Data Parser plugin, we need a few pieces of information from the user. The inputs guarantee that the plugin will be able to connect to UCD successfully, retrieve the necessary agent data, and optionally export it. Blow are the key inputs.
Input NameUI TypeRequiredDescription
UCD_URLTextBoxYesThe full URL for the UCD website.
UCD_UsernameTextBoxYesUsername to authenticate with UCD.
UCD_PasswordSecureBoxYesPassword for the UCD account.
Agent_Property_ListTextAreaBoxYesA newline-separated list of agent properties to be retrieved.
Export_Data_Into_CSVCheckBoxOptionalSelect to export the agent details to a CSV file.
File_PathTextBoxOptionalFile path or name for the CSV output.
ACCEPT_SELF_SIGNED_CERTIFICATECheckBoxOptionalAccept self-signed certificates during connection.

  1. Updated plugin.xml
    Below is the updated plugin.xml file, including the identified inputs, their types, and detailed descriptions. This configuration will make sure that the plugin asks for the input during its execution.
    plugin.xml

     <!-- The XML declaration <?xml version="1.0" encoding="UTF-8"?> specifies the version of XML being used and the character encoding for the document. -->
     <?xml version="1.0" encoding="UTF-8"?>
    
     <!-- Root element defining the IBM UCD plugin with its schema and namespace declarations -->
     <plugin xmlns="http://www.urbancode.com/PluginXMLSchema_v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    
         <!-- Plugin metadata including unique identifier, version, name, description, and tags -->
         <header>
             <identifier id="com.opensource" version="1" name="Agent Data Parser"/>
             <description>Plugin to get the list of agent and agent properties</description>
             <tag>Opensource/Custom/Utilities</tag>
         </header>
    
         <!-- Defines step in UCD process -->
         <step-type name="Get Agent Details List">
             <description/>
    
             <!-- Defines plugin properties including UCD URL, credentials, agent properties, export options, and file path -->
             <properties>
                 <property name="UCD_URL" required="true">
                     <property-ui type="textBox" label="UCD_URL"
                                 description="Enter the full URL for the UCD website. Here is an example: https://example.ucd.url:8443"
                                 default-value=""/>
                 </property>
                 <property name="UCD_Username" required="true">
                     <property-ui type="textBox" label="UCD Username"
                                 description="Enter Username to login into UCD"
                                 default-value=""/>
                 </property>
                 <property name="UCD_Password" required="true">
                     <property-ui type="secureBox" label="UCD Password"
                                 description="Enter Password to login into UCD"
                                 default-value=""/>
                 </property>
                 <property name="Agent_Property_List" required="true">
                     <property-ui type="textAreaBox" label="Agent Property List"
                                 description="List of properties sperated by new line"
                                 default-value=""/>
                 </property>
                 <property name="Export_Data_Into_CSV" required="true">
                     <property-ui type="checkBox" label="Export_Data_Into_CSV"
                                 description="When this checkbox is selected, a csv file will be created containing the agent's details"
                                 default-value="false"/>
                 </property>
    
                 <property name="ACCEPT_SELF_SIGNED_CERTIFICATE" required="true">
                     <property-ui type="checkBox" label="ACCEPT_SELF_SIGNED_CERTIFICATE"
                                 description="When this checkbox is checked, SELF SIGNED CERTIFICATE will be ACCEPTED"
                                 default-value="false"/>
                 </property>
    
                 <property name="File_Path" required="false">
                     <property-ui type="textBox" label="File_Path"
                                 description="File name in which data is to be added. For example, AgentData.csv"
                                 default-value=""/>
                 </property>
             </properties>
    
             <!-- Post-processing script to set the status based on the exit code -->
             <post-processing>
                 <![CDATA[
             if (properties.get("exitCode") != 0) {
                 properties.put("Status", "Failure");
             }
             else {
                 properties.put("Status", "Success");
             }
         ]]>
             </post-processing>
    
             <!-- Command to execute the Java JAR file with input and output property files -->
             <command program="${JAVA_HOME}/bin/java">
                 <arg value="-jar"/>
                 <arg file="IBM-DevOps-Deploy-Agent-Parser-1.0-jar-with-dependencies.jar"/>
                 <arg file="${PLUGIN_INPUT_PROPS}"/>
                 <arg file="${PLUGIN_OUTPUT_PROPS}"/>
             </command>
    
         </step-type>
     </plugin>
    
     ๐Ÿ”” Key Considerations When Modifying the plugin.xml File:
    
     1. The XML declaration (<?xml version="1.0" encoding="UTF-8"?>) and the root <plugin> element with namespace attributes (xmlns and xmlns:xsi) must remain unchanged, as they define the XML version, file encoding, and namespace required for the UCD plugin.
    
     2. Properties should be defined within the <properties> tag using the following format:
     <property name="<Property Name>" required="<true/false>">
        <property-ui type="<Property Type>" label="<Property Label>" description="<Property Description>" default-value="<Default Value>"/>
     </property>
    
         ๐‚๐จ๐ฆ๐ฆ๐จ๐ง ๐๐ซ๐จ๐ฉ๐ž๐ซ๐ญ๐ฒ ๐“๐ฒ๐ฉ๐ž๐ฌ ๐ข๐ง ๐ฉ๐ฅ๐ฎ๐ ๐ข๐ง.๐ฑ๐ฆ๐ฅ (๐€๐๐๐ข๐ญ๐ข๐จ๐ง๐š๐ฅ ๐ญ๐ฒ๐ฉ๐ž๐ฌ ๐š๐ซ๐ž ๐š๐ฏ๐š๐ข๐ฅ๐š๐›๐ฅ๐ž; ๐Ÿ๐ž๐ž๐ฅ ๐Ÿ๐ซ๐ž๐ž ๐ญ๐จ ๐ž๐ฑ๐ฉ๐ฅ๐จ๐ซ๐ž):
         โ†ณ textBox
         โ†ณ checkBox
         โ†ณ textAreaBox
         โ†ณ secureBox
    

๐’๐ญ๐ž๐ฉ ๐Ÿ‘: ๐”๐ฉ๐๐š๐ญ๐ž ๐ญ๐ก๐ž ๐ข๐ง๐Ÿ๐จ.๐ฑ๐ฆ๐ฅ ๐š๐ง๐ ๐ฎ๐ฉ๐ ๐ซ๐š๐๐ž.๐ฑ๐ฆ๐ฅ ๐Ÿ๐ข๐ฅ๐ž๐ฌ ๐š๐ฌ ๐ฉ๐ž๐ซ ๐ญ๐ก๐ž ๐ซ๐ž๐ช๐ฎ๐ข๐ซ๐ž๐ฆ๐ž๐ง๐ญ๐ฌ:

  • info.xml should contain metadata regarding the plugin, including version and descriptions, plus details about the versions it works with.

  • upgrade.xml contains modification logic if the plugin requires upgrading; modify to handle versioning and necessary transitions between plugin versions.

    ๐Ÿ’ก
    You must ensure the usage of proper XML structure and preserve elements when changing any of these files.

    info.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <pluginInfo>
          <author name="Aniket Kakde">
              <organization>example-org</organization>
              <email>example@gmail.com</email>
              <website>https://developer.ibm.com/urbancode/plugins/</website>
              <bio/>
          </author>
    
          <integration type="Automation"/>
    
          <tool-description>Agent Information parser for IBM UrbanCode Deploy</tool-description>
    
          <meta-html>
              <meta content="" name="description"/>
              <meta content="" name="keywords"/>  
          </meta-html>
    
          <release-version>1</release-version>
    
          <release-notes>
              <release-note plugin-version="1">
                  Plugin version 1
              </release-note>
          </release-notes>
    
      </pluginInfo>
    

    upgrade.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <plugin-upgrade xmlns="http://www.urbancode.com/UpgradeXMLSchema_v1" 
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <!--
          This section can be used to define upgrade paths between plugin versions.
          For example:
          <version from="1" to="2">
              <action name="Get Agent Details List" version="2"/>
          </version>
          For now, no upgrade changes are necessary.
          -->
      </plugin-upgrade>
    

๐’๐ญ๐ž๐ฉ ๐Ÿ’: ๐ˆ๐ฆ๐ฉ๐ฅ๐ž๐ฆ๐ž๐ง๐ญ ๐ญ๐ก๐ž ๐‹๐จ๐ ๐ข๐œ ๐‚๐จ๐๐ž
In this step, we implement the primary logic of our plugin. The main method performs the following operations:

  1. Determine the Working Directory:

    • The application first retrieves and prints the current working directory, which helps with debugging and ensuring that file paths are resolved correctly.
  2. Load Plugin Properties:

    • The plugin reads the configuration properties from a file passed as the first argument (args[0]). These properties include critical information such as the UCD URL, credentials, agent property list, and export options.
  3. Extract and Parse Inputs:

    • The required inputs are extracted from the properties file:

    • UCD_URL, UCD_Username, UCD_Password: For connecting to IBM UrbanCode Deploy.

    • Agent_Property_List: A newline-separated list of agent properties.

    • Export_Data_Into_CSV: A boolean flag to determine whether to create a CSV file.

    • File_Path: The name or path for the CSV output.

    • ACCEPT_SELF_SIGNED_CERTIFICATE: A flag indicating whether self-signed certificates are accepted.

  4. Instantiate the Core Processing Object:

    • With all required parameters collected and parsed, an instance of the GetAgentDetailsCustom class is created. This class encapsulates the logic to retrieve agent details and handle CSV export as needed.
  5. Handle Exceptions and Resource Cleanup:

    • The code uses a try-catch-finally block to ensure that any IO exceptions are caught and that the file input stream is properly closed, even if an error occurs.
  • Example Java Code

      public static void main(String[] args) {
          // Retrieve and display the current working directory for debugging purposes
          String workingDir = System.getProperty("user.dir");
          System.out.println("Working Directory: " + workingDir);
    
          // The properties file path is passed as the first argument
          String propsFilePath = args[0];
          Properties prop = new Properties();
          InputStream input = null;
    
          try {
              // Open and load the properties file
              input = new FileInputStream(propsFilePath);
              prop.load(input);
    
              // Extract the required properties from the file
              String UCDURL = prop.getProperty("UCD_URL");
              String UCDUsername = prop.getProperty("UCD_Username");
              String UCDPassword = prop.getProperty("UCD_Password");
              String ListString = prop.getProperty("Agent_Property_List");
              boolean CreateCSVFile = Boolean.parseBoolean(prop.getProperty("Export_Data_Into_CSV", "false"));
              String FileName = prop.getProperty("File_Path");
              boolean acceptSelfSignedCertificate = Boolean.parseBoolean(prop.getProperty("ACCEPT_SELF_SIGNED_CERTIFICATE", "false"));
    
              // Instantiate the GetAgentDetailsCustom class with the parsed properties
              GetAgentDetailsCustom agentDetails = new GetAgentDetailsCustom(
                      UCDUsername,
                      UCDPassword,
                      UCDURL,
                      acceptSelfSignedCertificate,
                      ListString,
                      CreateCSVFile,
                      FileName
              );
    
              // Further processing with agentDetails would occur here (e.g., executing the agent retrieval logic)
    
          } catch (IOException ex) {
              // Handle any exceptions that occur during file access or property loading
              ex.printStackTrace();
              System.exit(1);
          } finally {
              // Ensure the input stream is closed to prevent resource leaks
              if (input != null) {
                  try {
                      input.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                      System.exit(1);
                  }
              }
          }
      }
    

๐’๐ญ๐ž๐ฉ ๐Ÿ“: ๐”๐ฉ๐๐š๐ญ๐ž ๐ฉ๐จ๐ฆ.๐ฑ๐ฆ๐ฅ
Ensure that the pom.xml file is updated to reflect the required dependencies, plugin configurations, and any necessary versioning. This step is crucial to ensure that your plugin integrates smoothly with the build process and resolves the necessary libraries.

  • ๐Ÿ“ฃ The section in pom.xml defines how the project shall be compiled and packaged. It has the source code located within the src directory. The compiler is configured in maven-compiler-plugin that compiles source and target codes using Java 11. Packaging of the project into a JAR file by including all of its dependencies, maven-assembly-plugin has been used for this purpose. The manifest defines the main class as com.opensource.GetAgentDetailsCustom, and the jar-with-dependencies descriptor is used to include all libraries into the JAR. This sets up compilation and packaging of the project into a distributable, dependency-bundled JAR.

  • 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/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
    
          <groupId>org.example</groupId>
          <artifactId>IBM-DevOps-Deploy-Agent-Parser</artifactId>
          <version>1.0</version>
    
          <properties>
              <maven.compiler.source>11</maven.compiler.source>
              <maven.compiler.target>11</maven.compiler.target>
              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
          </properties>
    
          <build>
              <sourceDirectory>src</sourceDirectory>
              <plugins>
                  <plugin>
                      <artifactId>maven-compiler-plugin</artifactId>
                      <version>3.5.1</version>
                      <configuration>
                          <source>11</source>
                          <target>11</target>
                      </configuration>
                  </plugin>
                  <plugin>
                      <artifactId>maven-assembly-plugin</artifactId>
                      <configuration>
                          <archive>
                              <manifest>
                                  <mainClass>com.opensource.GetAgentDetailsCustom</mainClass>
                              </manifest>
                          </archive>
                          <descriptorRefs>
                              <descriptorRef>jar-with-dependencies</descriptorRef>
                          </descriptorRefs>
                      </configuration>
                  </plugin>
              </plugins>
          </build>
    
          <dependencies>
    
              <!-- https://mvnrepository.com/artifact/org.json/json -->
              <dependency>
                  <groupId>org.json</groupId>
                  <artifactId>json</artifactId>
                  <version>20230618</version>
              </dependency>
    
          </dependencies>
    
      </project>
    

๐’๐ญ๐ž๐ฉ ๐Ÿ”: ๐๐ฎ๐ข๐ฅ๐ ๐ญ๐ก๐ž ๐๐ซ๐จ๐ฃ๐ž๐œ๐ญ
To build the project, use the following Maven command:

mvn clean compile assembly:single

This command will clean any previously compiled files, compile the source code, and package the project into a JAR file. The resulting JAR file will be located in the target directory.


๐’๐ญ๐ž๐ฉ ๐Ÿ•: ๐๐š๐œ๐ค๐š๐ ๐ž ๐…๐ข๐ฅ๐ž๐ฌ ๐ญ๐จ ๐๐ฎ๐ข๐ฅ๐ ๐ญ๐ก๐ž ๐๐ฅ๐ฎ๐ ๐ข๐ง
After building the JAR file in Step 5, follow these steps to package your plugin:

  1. Copy the JAR file generated in the target directory and place it in the same directory where your plugin.xml, upgrade.xml, and info.xml files are located.

  2. Compress all the files (JAR file, plugin.xml, upgrade.xml, and info.xml) into a.zip archive.

  3. This will result in a ZIP file containing all the components for the plugin to be deployed.


๐’๐ญ๐ž๐ฉ ๐Ÿ–: ๐”๐ฉ๐ฅ๐จ๐š๐ ๐๐ฅ๐ฎ๐ ๐ข๐ง ๐ข๐ง๐ญ๐จ ๐”๐‚๐ƒ.
Once the ZIP file containing the JAR, plugin.xml, upgrade.xml, and info.xml is ready, follow these steps to upload it into IBM UrbanCode Deploy (UCD):

  1. Log in to the UCD instance.

  2. Navigate to "Settings" in the UCD dashboard.

  3. Click on "Automation Plugins" option.

  4. Click on "Load Plugin" option.

  5. Select the ZIP file you created in Step 6 and upload it.

  6. After uploading, UCD will process the plugin, and you should see it listed in the available plugins.

๐Ÿ’ก
Now, the plugin is ready to be used in UCD for deployment or automation tasks!

RoadMap


Sample Output


Advantages Over Manual Processes

  • No Resource Dependency:
    Automation reduces the need for manual intervention.

  • Reduced Human Error:
    Minimizes mistakes common in manual data handling.

  • 98% Time Savings:
    Fetches 6000 agents in 1 hour 40 minutes versus 300 hours manually.


Useful Resource

๐Ÿ’ก

๐Ÿ“œ License

CC BY 4.0

IBM DevOps Deploy (IBM UrbanCode Deploy) Custom Plugin Development ยฉ 2025 by Aniket Kakde is licensed under [CC BY 4.0](creativecommons.org/licenses/by/4.0). You are free to share and adapt this content with proper attribution.

ย