Overview

This feature is a technology preview. Functionality may change in future versions.

This feature is intended for advanced users.

Note:

We added this functionality in cPanel & WHM version 64.

Important:

The Provider module must be a subclass of the Cpanel::iContact::Provider module.

You do not need knowledge of the ancestor module.

This document outlines how to create a custom notification for cPanel & WHM version 64 and later. This sends cPanel & WHM server alert notifications to an Internet Relay Chat server, Slack, or related service. The custom notification consists of two Perl modules. The following steps describe how to create and configure these modules.

Create a custom notification

Create the Schema module

To create the first Perl module (Schema), perform the following steps:

Create a Perl module in the following directory, where $MODULE_NAME represents your new module's name:

/var/cpanel/perl/Cpanel/iContact/Provider/Schema/$MODULE_NAME.pm

Use the following module as a an example for your module:

Click to view...

Note:

If your Schema module requires external modules, place them within the checkval functions that they intend to use.

package Cpanel::iContact::Provider::Schema::Example; # Change 'Example' to your Service name
use strict;
use warnings;
# Use any modules from our installed CPAN modules here.
sub get_settings {
return {
'EXAMPLEAUTHTOKEN' => {
'shadow' => 1, # Flag for saving to /etc/wwwacct.conf.shadow or /etc/wwwacct.conf
'type' => 'password', # This maps to an HTML input tag's "type" attribute. Perfect for things like passwords or API bearer tokens.
'checkval' => sub {
# Not really much to do here, since I'm not actually aware of a good validation regex for these tokens.
my $value = shift();
# Do some validation here to make sure $value is either a) a sanitized version of what was input via the UI OR
# b) a blank string, as it failed to validate.
# NOTE: Do not establish whether the parameter is *valid* for your service (in this example). Instead, this ensures that you format things the way you want them.
# As an example, you can input non-resolving email addresses in for the email notification field in Basic Setup, it will just fail to send when we go to actually do that.
# Generally we expect integrators to follow this model as well. To reject an email address because it does not follow the RFC for a valid address string for example, would make sense here though.
...
return $value;
},
'label' => 'Example Service Auth Token',
'help' => 'Some string that would tell people how to obtain this, what it should look like, etc.',
},
'EXAMPLESERVICEHOST' => {
'shadow' => 1,
'type' => 'text',
'checkval' => sub {
my $value = shift();
...
return $value;
},
'label' => 'Example Service API URI',
'help' => 'Some string that would tell people how to obtain this, what it should look like, etc.',
},
# NOTE to 3rd party integrator - Only have one property prefixed with CONTACT, as that one will be the 'triggering' property for notifications.
# In the logs, the TYPE of the notification will show up as CONTACT<NAME> where <NAME> is your TYPE.
'CONTACTEXAMPLE' => {
'name' => 'Example', # Needed to tell cPanel what provider module to load over in /var/cpanel/perl/Cpanel/iContact/Provider/
'shadow' => 1,
'type' => 'text',
'checkval' => sub {
my $value = shift();
...
return $value;
},
'label' => 'Example Service user to notify',
'help' => 'Some string that would tell people how to obtain this, what it should look like, etc.',
}
};
}
sub get_config {
return {
'default_level' => 'All', # Maps to what you'd see in the WHM >> Contact Manager UI as the default notification level. In /var/cpanel/clevels.conf, this would be translated to '3'.
'display_name' => 'Example', # Maps to what your provider shows up as in the WHM >> Contact Manager UI.
'icon_name' => 'Example', # Maps to what your icon is named. Currently irrelevant, as it does nothing to help your icon load, and falls back to 'display_name' above if not set.
'icon' => ... # A long Data URI (ex. "data:image/png;base64,$my_image_base64"). Thankfully these only display at 16x16px, so you can scale down the image first.
};
}
1;

Input relevant information in the get_settings() and get_config() subroutines.

Note:

The target service (for example, Slack) uses this module to validate your provider's settings and configuration, and to establish how to present the information in the user interface.

Create the Provider module

Create the second Perl module (Provider) in the following directory, where $MODULE_NAME represents your new module's name:

/var/cpanel/perl/Cpanel/iContact/Provider/$MODULE_NAME.pm

Use the following module as a an example for your module:

Click to view...

package Cpanel::iContact::Provider::Example;
use strict;
use warnings;
# You must use the following, as all iContact providers are subclasses of this.
use parent 'Cpanel::iContact::Provider';
# You *may* also want to use some CPAN modules here for contacting your service,
# in particular, one of the WebService, LWP/HTTP or Net namespaced modules. # (See NOTE: below) Try::Tiny would probably be nicer than block eval too.
# NOTE: We strongly recommended that you require *all* external dependencies
# at runtime. These modules load every time iContact notifications are sent if
# you 'use' them. When you 'use' modules, you can negatively impact the memory
# footprint of the parent process responsible for sending iContact
# notifications.
sub send { # Here is where we define how to reach out and touch your service.
my ($self) = @_;
# NOTE: If you use Data::Dumper, get the output of this hashref --
# the 'html_template' contents may corrupt your tty due to some of the
# symbols translating into control codes for the terminal.
# Just run 'reset' on your terminal to clear any corruption of that
# (or just don't dump that before decoding the UTF8 chars within it).
# This hashref contains the recipients ('to' arrayref) and the processed
# notification templates, among other things.
my $args_hr = $self->{'args'};
# This will contain any of the non-CONTACT prefixed properties you defined
# in the schema module.
my $contact_hr = $self->{'contact'};
my @errs;
my $subject_copy = $args_hr->{'subject'};
my $body_copy = ${ $args_hr->{'text_body'} };
require Encode;
my $subject = Encode::decode_utf8( $subject_copy, $Encode::FB_QUIET );
my $body = Encode::decode_utf8( $body_copy, $Encode::FB_QUIET );
foreach my $destination ( @{ $args_hr->{'to'} } ) {
eval {
# Try to do something to contact your service and deliver the
# notification payload here. The author *should* die within this
# block if something returns a failure response but doesn't die.
my $response;
$self->_send(
'destination' => $destination,
'subject' => $subject,
'content' => $body
) || die "Sending to $destination failed: " . $self->_last_error();
};
push( @errs, $@ ) if $@;
}
# After all notification send attempts complete, die if one or more
# failed
if (@errs) {
die "One or more notification attempts failed. Details below:\n"
. join( "\n", @errs );
}
return 1;
}
# Ensure that you define all of the other internal methods defined below if you
# need them. You will notice in my example that I had a _send and _last_error
# subroutine. How you wish to implement these is up to you, however.
...
1;

Input relevant information in the send() subroutine.

Note:

This module defines how your provider communicates with your service, and uses the settings we defined in our Schema module.

cPanel, WebHost Manager, and WHM are registered trademarks of cPanel, Inc. for providing its computer software that facilitates the management and configuration of Internet web servers. ®2016 All rights reserved.