Activity
What is an Activity? An Activity in ZervicePoint is a building block when creating a Workflow. Activities are the things that "do the work" and make things happen in your Workflow. An Activity can be either one of the built-in activities shipped with ZervicePoint, Activities made available by buying a Plugin or a custom Activity that you have built yourself.
- Built-in: Examples are Send Email, Set State, Assign, Approval etc. Part of the core product. Runs on Process System.
- Inventoried: Examples are New-ADUser, Enable-S4BUser, Get-ZPO365User. Scripts from disk. Can be custom made or from plugins. Runs on Provisioning System.
Custom Activities
Custom Activites are typically written when we want a step in our workflow to perform a CRUD (Create, Read, Update, Delete) action in a target system (e.g Active Directory). You can also use them for business logic to generate names etc from other systems. For business logic that does not require input from another system, we recommend using the built-in Code Activity.
- Quickstart - How to create a custom activity
- ProvisioningSystem Role
- Understanding zervicepoint data train
Info
Before writing your own custom activites, you should be familiar with writing your own PowerShell functions.
Parameters
You can add parameters to your activites. You can either bind parameters to variables or enter a static value as input.
SiteName, Owners and Members parameters are bound to variables while TemplateName is set to a static value.
Tip
If you have several activites using the static input value, you can create a variable and give it a default value or use a assign activity to set it and bind the parameter to the variable.
To add a parameter in a powershell function you must include a parameter block.
function New-TeamSite
{
param(
[Parameter(Mandatory=$true)]
[string]$SiteName,
[string]$TemplateName,
[string]$Owners,
[string]$Members
)
# Code to add new team site ...
# output
return @{}
}
To learn more about powershell functions, follow this link about_functions
What if I add a new parameter to an existing function?
When adding new parameters to an existing activity. You must re-add the item in the workflow. This example show that the previous version of Get-DayOfWeek does not include the new Format parameter.
Additional Parameters
In order to pass parameters created as Additional Parameter, the function must include a parameter called $Parameters. This must be a hashtable and it will include the defined parameters and the additional parameters. The $Parameters parameter should include [parameter(Mandatory = $false, ParameterSetName = "Hidden")]
setting.
Example
param(
[string]$Test,
[parameter(Mandatory = $false, ParameterSetName = "Hidden")]
[hashtable]$Parameters
)
# $Parameters will include the following keys if input is the example above.
Name Value
---- -----
myParameter hello world
Test 123
Tip
As the $Parameters parameter will also include defined parameters. You can use the cmdlet Get-PFAdditionalParameter to only return the additional parameters. Get-PFAdditionalParameter is part of the PowerFrame module which is included in all our plugins.
ParameterSetName "Hidden"
Hides a parameter from the workflow editor. $Parameters and $Config should always be part of the 'Hidden' parameter set name in order to prevent passing multiple values into those parameters.
param(
[parameter(Mandatory = $false, ParameterSetName = "Hidden")]
[hashtable]$Parameters,
[parameter(Mandatory = $false, ParameterSetName = "Hidden")]
[hashtable]$Config
)
Config Parameter
The $config parameter must be a hashtable and it will automatically contain the following data:
Key | Value | Source | Comment |
---|---|---|---|
scriptpath | C:\Plugin\Example\Activities | XML | Location of modules to import |
The provider.xml file used to locate which location to load a plugin from and it can include keys within it's configuration block.
The following provider.xml would add the DomainController and SearchBase to the $config hashtable.
<?xml version="1.0" encoding="utf-8"?>
<providers>
<provider name="Example Plugin">
<assembly type="Zipper.ZervicePoint.ProvisioningSystem.PowerShellProvider.PowerShellEngine" assemblyFile="C:\Program Files\Zipper\ZervicePoint\Web\ProvisioningSystem\Bin\Zipper.ZervicePoint.ProvisioningSystem.PowerShellProvider.dll"/>
<configuration>
<add key="scriptpath" value="C:\Plugin\Example\Activities\" />
<add key="DomainController" value="dc01.example.com" />
<add key="SearchBase" value="DC=example,DC=com" />
</configuration>
</provider>
</providers>
To pass the keys from the configuration and into the powershell function, you must include the $config parameter.
[parameter(Mandatory = $false, ParameterSetName = "Hidden")]
[hashtable]$Config
Output
Custom activities should output a hashtable with output details of the activity.
The output hashtable will be compared with the variable list, if there are any matches between the **Key* and VariableName, then the variable will be updated with the value from the activity output.
Example 1 - Return variable called "DayOfWeek" with value from Get-Date cmdlet.
function Get-DayOfWeek {
@{
DayOfWeek = (Get-Date).DayOfWeek.ToString()
}
}
#Output
Get-DayOfWeek
Name Value
---- -----
DayOfWeek Monday
Additional reading: about_Hash_Tables
Example 2 - Return output after creating a Active Directory user. We've also added very simple error handling and different output depending on the outcome.
function New-ADUserExample {
Param(
[Parameter(Mandatory=$true)]
[string]$Username,
[string]$Firstname,
[string]$Lastname,
[string]$OUPath
)
try {
$newADUser = New-ADUser -Name $Username -SamAccountName $Username -GivenName $Firstname -Surname $Lastname -Path $OUPath -Passthru:$true -ErrorAction Stop
if ($null -ne $newADUser) {
$ht = @{
State = "Successfully created AD object"
StatusCode = 0
ObjectGUID = $newADUser.ObjectGUID
SamAccountName = $newADUser.SamAccountName
DistinguishedName = $newADUser.DistinguishedName
}
} else {
$ht = @{
State = "Failed to create AD object"
StatusCode = 1
}
}
} catch {
$ht = @{
State = "An error occured when creating AD object"
ExceptionMessage = $_.exception.message
StatusCode = 2
}
}
$ht
}
# Output case 1
Name Value
---- -----
SamAccountName user0002
DistinguishedName CN=user0002,OU=test,DC=example,DC=com
ObjectGUID a0bd9480-f15a-4cb2-943b-a22bfb24d32d
StatusCode 0
State Successfully created AD object
# Output case 2
Name Value
---- -----
State Failed to create AD Object
StatusCode 1
# Output case 3
Name Value
---- -----
ExceptionMessage The specified account already exists
StatusCode 2
State An error occured when creating AD object
With the output above, we could add logic in our workflow to do different activities, such as reporting an alert when State 1 or 2 occured. In the example below, the workflow will perform different actions depending on the result of the New-ADUserExample function.
Workflow example
Output Data types
Zervicepoint supports the following data types as outputs from an activity.
- String
- Boolean
- Decimal
- Datetime
Warning
If you return unsupported data types, the activity will fail to return the data to the workflow.
Prefix
When you use multiple custom activities in your workflow, you may come across the issue with activities outputing the same key values as other activities. This can cause an issue with variables being "overwritten" as they are updated by another activity.
This can either be solved by assigning activities to another variable after the output, but as there is not an unlimited number of variables that can be used in a workflow, this is not always recommended.
To solve this you should include a parameter called $Prefix, this could be used to then add a prefix before the output keys.
function Get-ExampleUser
{
param(
[string]$Identity,
[string]$Prefix
)
$getADUser = Get-ADUser -Identity $Identity
$ht = @{
"$($Prefix)ObjectGUID" = $getADUser.ObjectGUID
"$($Prefix)SamAccountName" = $getADUser.SamAccountName
}
return $ht
}
# Output
Get-ExampleUser -Identity user001 -Prefix test
Name Value
---- -----
testObjectGUID c8108ec6-ff33-4cc8-9302-e5a960ca5111
testSamAccountName user001
Add prefix using Add-PFHashTablePrefix
You can use "Add-PFHashTablePrefix" to easily add a prefix to an existing hashtable. Add-PFHashTablePrefix is part of the PowerFrame module which is included in all our plugins.
$ht = @{
SamAccountName = "User001"
ObjectGUID = "c8108ec6-ff33-4cc8-9302-e5a960ca5111"
Mail = "user001@example.com"
GivenName = "user"
Surname = "001"
}
$htprefix = Add-PFHashTablePrefix -InputObject $ht -Prefix "MyPrefix"
$htprefix
#output
Name Value
---- -----
MyPrefixSamAccountName User001
MyPrefixMail user001@example.com
MyPrefixObjectGUID c8108ec6-ff33-4cc8-9302-e5a960ca5111
MyPrefixGivenName user
MyPrefixSurname 001
Here's is the function we use for Add-PFHashTablePrefix
function Add-PFHashTablePrefix
{
<#
.SYNOPSIS
Add prefix to an existing hash table
.DESCRIPTION
Add-PFHashTablePrefix adds prefix to an existing hash table
.PARAMETER InputObject
Specifies the hashtable object to add prefix to
.PARAMETER Prefix
Specifies the prefix to add
.EXAMPLE
$hashtable = @{
"ZP" = "ZervicePoint"
}
Add-PFHashTable -InputObject $hashtable -Prefix "Magic"
The example above returns the following hashtable:
@{
"MagicZP" = "ZervicePoint"
}
.NOTES
Add-PFHashTablePrefix is an internal function and part of the ZervicePoint.Utility module.
.LINK
https://www.zervicepoint.com
#>
[CmdLetBinding(DefaultParameterSetName = "InputObject")]
[OutputType([System.Collections.Hashtable])]
param (
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[hashtable]$InputObject,
[Parameter(Mandatory=$false)]
[AllowNull()]
[AllowEmptyString()]
[string]$Prefix
)
process {
if ($Prefix) {
$hashTable = @{}
foreach ($Object in $InputObject.GetEnumerator()) {
$hashTable[$( $prefix + $Object.Key )] = $Object.Value
}
return $hashTable
} else {
return $InputObject
}
}
}
Quickstart - How to create a custom activity
Before you begin you must have ProvisioningSystem installed
How to setup ProvisioningSystem role.
In order to create our own activity, we will need to create the following on the provisioningsystem server.
- A PowerShell Module
- A plugin xml file (pluginname.provisioningsystem.provider.xml)
Create a zervicepoint plugin in PowerShell
Start PowerShell (run as admin)
Create the following folder structure
C:\Plugin\ZPDocs\Activites\Activity.ZPDocs
To quickly create the structure above you can run the following powershell commands
New-Item -ItemType Directory -Path 'C:\Plugin\ZPDocs\Activities\Activity.ZPDocs'
Create PowerShell Module Manifest
New-ModuleManifest -Path C:\Plugin\ZPDocs\Activities\Activity.ZPDocs\Activity.ZPDocs.psd1 `
-RootModule "Activity.ZPDocs.psm1" `
-FileList @("Activity.ZPDocs.psd1","Activity.ZPDocs.psm1") `
-FunctionsToExport @('*') `
-PowerShellVersion 3.0
Write a function to PowerShell Module
Copy the function and insert it into the .psm1 file
$psm1 = @"
function Get-DayOfWeek {
@{
DayOfWeek = (Get-Date).DayOfWeek.ToString()
}
}
"@
$psm1 | Out-File 'C:\Plugin\ZPDocs\Activities\Activity.ZPDocs\Activity.ZPDocs.psm1' -Encoding UTF8
Create a plugin xml
The provisioningsystem provider xml contain metadata for the plugin, name and scriptpath. It is also possible to extend this file with custom keys that can contain configuration related to the plugin. (e.g URLs etc)
Copy and paste the following code in a powershell prompt to create a plugin XML file.
$pluginxml = @"
<?xml version="1.0" encoding="utf-8"?>
<providers>
<provider name="Learn zervicepoint">
<assembly type="Zipper.ZervicePoint.ProvisioningSystem.PowerShellProvider.PowerShellEngine" assemblyFile="C:\Program Files\Zipper\ZervicePoint\ProvisioningSystem\Providers\PowerShell\Zipper.ZervicePoint.ProvisioningSystem.PowerShellProvider.dll" />
<configuration>
<add key="scriptpath" value="C:\Plugin\ZPDocs\Activities\" />
</configuration>
</provider>
</providers>
"@
$pluginxml | Out-File 'C:\Program Files\Zipper\ZervicePoint\ProvisioningSystem\ZPDocs.provisioningsystem.providers.xml' -Encoding UTF8
Trigger Inventory
To inventory new activties, you can choose one of the following methods.
Restart-Service -Name ProvisioningSystem
# or
& 'C:\Program Files\Zipper\ZervicePoint\ProvisioningSystem\Zipper.ZervicePoint.ProvisioningSystem.Service.exe' /inventoryonly
After the inventory is complete, it should soon be searchable in the providers page (AdminWeb). If it does not show up, check the zervicepoint event log.
Now that the activity is inventoried, you can use it in your workflow. This activity will return the Key "DayOfWeek" that can be mapped to a string variable called "DayOfWeek".