Basic - Reporting Plugin

4 minute read

Introduction

This basic tutorial provides instructions to create a basic reporting plugin called SampleReporting that demonstrates how a plugin can be used to provide numbers for RCC dashboard metrics. The purpose of this tutorial is to demonstrate usage of plugins in RCC that do not require connecting to a third party tool. Please notice that this basic tutorial uses randomly generated numbers instead of real data from a third-party tool.

Prerequisites

These are assumptions for this Tutorial.

  • Introductory Tutorial has been completed.

  • The pdk tool is installed and setup.

  • An active CloudBees CD instance with DevOps Insight.

  • Internet connection.

  • A GitHub account.

Step 1 : Generate a plugin using sample spec from GitHub

After making sure pdk is available in your PATH, create a plugin workspace, typing the name SampleReporting for the plugin. Copy pluginspec.yaml from the cloned repository to the config directory of your plugin and generate the plugin.

cd ~/work
git clone https://github.com/electric-cloud-community/flowpdf  ~/temp/flowpdf
`pdk generate workspace`
cp ~/temp/flowpdf/perl/SampleReporting/config/pluginspec.yaml SampleReporting/config
cd SampleReporting
`pdk generate plugin`

Step 2 : Modify Reporting.pm

Modify Reporting.pm under flowpdf/SampleReporting/dsl/properties/perl/lib/FlowPlugin/Reporting/ to add an import to Datetime and a basic implementation of all its generated methods. Replace the entire content of Reporting.pm as follows. Optionally, you can compare the content below with generated code and do each of these changes one by one.

package FlowPlugin::SampleReporting::Reporting;
use Data::Dumper;
use base qw/FlowPDF::Component::EF::Reporting/;
use FlowPDF::Log;
use DateTime;
use strict;
use warnings;

# todo more sample boilerplate
sub compareMetadata {
    my ($self, $metadata1, $metadata2) = @_;

    my $value1 = $metadata1->getValue();
    my $value2 = $metadata2->getValue();
    # Implement here logic of metadata values comparison.
    # Return 1 if there are newer records than record to which metadata is pointing.
    return 1;
}

sub initialGetRecords {
    my ($self, $pluginObject, $limit) = @_;

    # build records and return them
    # todo required fields

    my $records = [{
        buildNumber => int rand 998889,
        test1 => 'test',
    }];

    return $records;
}

sub getRecordsAfter {
    my ($self, $pluginObject, $metadata) = @_;

    # build records using metadata as start point using your functions

    my $records = [{
        buildNumber => int rand 89128912,
        test1 => 'test'
    }];

    return $records;
}

sub getLastRecord {
    my ($self, $pluginObject) = @_;
    my $lastRecord = {buildNumber => int rand 938193};
    return $lastRecord;
}

sub buildDataset {
    my ($self, $pluginObject, $records) = @_;

    my $dataset = $self->newDataset(['build']);
    my $context = $pluginObject->getContext;
    my $params = $context->getRuntimeParameters();

    for my $row (@$records) {
        # now, data is a pointer, you need to populate it by yourself using it's methods.
        my $data = $dataset->newData({
        reportObjectType => 'build',
    });

    my $today = DateTime->now;
    # Just some random data
    $row->{source} = "Test Reporting";
    $row->{pluginName} = '@PLUGIN_NAME@';
    $row->{projectName} = $context->retrieveCurrentProjectName;
    $row->{releaseProjectName} = $params->{releaseProjectName};
    $row->{releaseName} = $params->{releaseName};
    $row->{timestamp} = $today->ymd . 'T' . $today->hms . '.000Z';
    my $status = rand() > 0.5 ? 'SUCCESS' : 'FAILURE';
    $row->{buildStatus} = $status;
    $row->{pluginConfiguration} = $params->{config};
    $row->{endTime} = $today->ymd . 'T' . $today->hms . '.000Z';
    $row->{startTime} = $today->ymd . 'T' . $today->hms . '.000Z';
    $row->{duration} = (int rand 9839) * 1000;

    for my $k (keys %$row) {
        $data->{values}->{$k} = $row->{$k};
    }

    }
    return $dataset;
}

1;

Step 3 : Modify SampleReporting.pm

Modify SampleReporting.pm under flowpdf/SampleReporting/dsl/properties/perl/lib/FlowPlugin/ to add a basic implementation for collectReportingData. Replace the entire content of collectReportingData as follows. Optionally, you can compare the content below with generated code and do each of these changes one by one.

sub collectReportingData {
    my $self = shift;
    my $params = shift;
    my $stepResult = shift;


    my $buildReporting = FlowPDF::ComponentManager->loadComponent('FlowPlugin::SampleReporting::Reporting', {
        reportObjectTypes     => [ 'build' ],
        metadataUniqueKey     => int rand 89898,
        payloadKeys           => [ 'buildNumber' ]
    }, $self);
    $buildReporting->CollectReportingData();

}

Step 4 : Build, install, promote and configure the plugin

Use pdk to build the plugin. Install the zip in CloudBees CD and promote it. Create a plugin configuration with any name your prefer, filling in the required fields just to make sure they are non-empty. As the plugin configuration for this sample is a placeholder, the values you type for URL or credentials will not be used.

Step 5 : Setup RCC

Navigate to the Release Command Center DevOps Insight Dashboard and configure the Data Source as follows.

Once done it should look similar to the image below.

Step 6 : Examine the schedules created and numbers in the RCC dashboard

Notice the following schedules that get automatically created.

Notice the CollectReportingData procedure getting called.

Notice the numbers getting populated in the RCC Dashboard.

Step 7 : Summary

This summary is provided in order to help a developer conceptualize the steps involved in the creation of this plugin.

  • Specification

    • pluginspec.yaml provides the declarative interface for the plugin procedure CollectReportingData.

  • Generated code

    • pdk generates boiler plate code for procedures in Reporting.pm as well as SampleReporting.pm. The former consists of boiler plate code for the implementation of CollectReportingData, while the later provides the Procedure Interface that gets invoked by RCC.

    • pdk also generates the boiler plate code for creating the DOIS DSL scripts (see image below). When creating or modifying the data source in RCC, these DSL scripts get executed. Their execution results in creating schedules which in turn call CollectReportingData.

  • User Modifications

    • Implement compareMetadata, initialGetRecords, getRecordsAfter, getLastRecord, buildDataset.

    • Note that all the above methods are part of the Reporting component.