Server side hooks

Server Side hooks are used to customize and enforce business logic on certain Helix IPLM commands. Alias lock and unlock behavior, IP edit field checking and Property validation and permissions enforcement are some common examples of the application of Server Side hooks.

Server side hooks

Hooks are customer defined scripts that are run before certain actions. As a result of running these scripts, if the action requested with the payload sent does not pass the check, the hook script will return 'failed' status and the server will be aborted. The server will then reject the action because the hook failed.

Configuration

The location of the hook script must be configured in the neo4j.conf file by setting:

mdx.hook_script=/path/to/executable

The hook script must be a file, executable by the user running Neo4j PiServer plugin (usually neo4j), using the first command line argument to determine which Helix IPLM call triggered the hook. The business logic can be applied in a function within the hook or on separate scripts to be called by the hook. 

Note:  Hooks do not accept the tilde (~) character.

CLI command First command line argument
pi ip add iplv-create

pi ip edit

pi ip properties

iplv-edit
pi ip copy iplv-copy

pi alias lock

pi alias unlock

alias-lock

Upon trigger of the hook, PiServer will write to stdin a payload composed of the data sent to the server during the Helix IPLM call that triggered the hook. The same payload will be written to stdin regardless of the API used to make the Helix IPLM call.

Important:  The output of the hook will be returned back to the user that initiated the action that caused the hook to run if an error occurred (exit code 1). Therefore, the hook must be carefully written to avoid potential data leaks.

Example server side hook script

An example server side hook that modifies the default Alias lock/unlock behavior can be found on the page: Server side hook example - Alias lock/unlock. An example hook script can also be found under the piserver installation path (eg /usr/share/mdx/products/piserver/scripts/hook_script.py)

Timeout parameter

When a hook is executing on a target object, the object remains locked for the duration of the hook execution. If another commands executes a hook on the same target object, this will produce a 'ServerHookConcurrencyError' as two hook operations may not execute on the same target object at the same time. 

This concurrent hook execution can be prevented by configuring 'mdx.hook_lock_wait_timeout' parameter (default is 3 seconds) in the neo4j.conf file. See Neo4j Configuration for more information. In this case, the second hook execution will wait for up 3 seconds for the target object to be released. For customers that expect multiple concurrent hook executions on same object, increasing this parameter value is recommended. The parameter value is expressed in milliseconds.

Properties and server side hooks

The changed_properties field is provided to both the iplv-create and iplv-edit payloads. This field lists the name and the new value (after change) of any properties that have changed due to the operation. The current value of the property (before change) is not included in the payload, but can be retrieved in an additional API call.

When used in conjunction with the 'user' section, the following typical use cases are supported for properties in server side hooks:

  • Check if the user performing the property edit is a member of the admin, else reject the action
  • Check if the user is in a specific group, else reject the action
  • Check if other external criteria are met prior to allowing the property value change, which enables implementing workflows

  • Reject the action if the property value has already been set, creating write-once properties.

The 'changed_properties' section will only be set on an IP creation that is initiated from the Public API or IPLM Web, it is currently not possible to set property values at the time of IP creation from PiCLI via the 'pi ip edit' command. From PiCLI, properties may be set via the 'pi ip properties' command as a second step after creation, in which case they will trigger the 'iplv-edit' hook.

The list of 'changed-properties' will contain all the changed properties set on the IP or IPV rather than the full list of properties (the changed-properties list will contain all the properties in the case of the iplv-create hook). 

The 'groups' field for the 'user' is a flattened list of all recursive groups for the given user, any permissions information that is required by the hook script can be retrieved via the Public API. The Public API will not return a field value if the property has not been set yet. 

Supported actions

Creating an IPLV (iplv-create)

CLI Public API
pi ip add
POST public/v1/iplvs
{
    "user": {
        "id": "string",
        "name": "string",
        "is_admin": boolean,
        "groups": [{
            "id": "string",
            "name": "string"
        }]
    },
    "ip": {
        "id": "string",
        "name": "string",
        "library": {
            "name": "string",
            "id": "string"
        },
        "description": "string",
        "dm_type": {
            "name": "string",
            "id": "string"
        },
        "host": "string",
        "icon": "string",
        "hooks": {
            "hook_post_load": "string",
            "hook_post_update": "string",
            "hook_pre_release": "string",
            "hook_post_release": "string"
        },
        "changed_properties": [{
            "id": "string",
            "name": "property_name",
            "changed_value": [ <value> ]
        }]
    },
    "ipl": {
        "id": "string",
        "name": "string",
        "icon": "string"
    },
    "ipv": {
        "id": "string",
        "version": "string",
        "version_message": "string",
        "repo_path": "string",
        "project_props": "string",
        "icon": "string",
        "resources": [{
            "alias": {
                "id": "string",
                "name": "string"
            },
            "ipv": {
                "id": "string",  <IPV ID >

               "fqn": {
                    "library": "string",
                    "ip": "string",
                    "line": "string",
                    "version": "long"
                }
            },
            "private_resource": False
        }],
        "changed_properties": [{
            "id": "string",
            "name": "property_name",
            "changed_value": [ <value> ]


        }]
    }
}

Editing an IPLV (iplv-edit)

CLI Public API
pi ip edit
PUT public/v1/iplvs/<ipv_uuid>

{
    "user": {
        "id": "string",
        "name": "string",
        "is_admin": boolean,
        "groups": [{
            "id": "string",
            "name": "string"
        }]
    },
    "ip": {
        "name": "string",
        "library": {
            "name": "string",
            "id": "string"
        },
        "description": "string",
        "dm_type": {
            "name": "string",
            "id": "string"
        },
        "host": "string",
        "icon": "string",
        "hooks": {
            "hook_post_load": "string",
            "hook_post_update": "string",
            "hook_pre_release": "string",
            "hook_post_release": "string"
        },
        "changed_properties": [{
            "id": "string",
            "name": "property_name",
            "changed_value": [ <value> ]       

      }]
    },
    "ipl": {
        "name": "string",
        "icon": "string"
    },
    "ipv": {
        "version_message": "string",
        "version": "string",
        "repo_path": "string",
        "project_props": "string",
        "icon": "string",
        "resources": [{
            "alias": {
                "id": "string",
                "name": "string"
            },
            "ipv": {
                "id": "string",
                "fqn": {
                    "library": "string",
                    "ip": "string",
                    "line": "string",
                    "version": "long"
                }
            },
            "private_resource": False
        }],
        "changed_properties": [{
            "id": "string",
            "name": "property_name",
            "changed_value": [ <value> ] 

        }]
    }
}

Copying an IPLV (iplv-copy)

CLI Public API
pi ip copy
POST public/v1/iplvs/<ipv_uuid>/copy-to-new-ip
POST public/v1/iplvs/<ipv_uuid>/copy-to-new-ipl

{
    "source" : {
        "id": "string - Source IPV uuid",
        "fqn": {
            "library": "string - Source IP Library name",
            "ip": "string - Source IP name",
            "line": "string - Source IP Line name",
            "version": Long - Source IP version 
        }
    },
    "target" : {
        "fqn": {
            "library": "string - Target IP Library name",
            "ip": "string - Target IP name",
            "line": "string - Target IP Line name" <TRUNK if not specified>,
            "version": 0 <always 0>        }
    },
    "repo_path": "string - Target IPV repo path" <omitted for CONT type>,
    "version_message": "string - Target IPV version message"}

Locking and unlocking an alias (alias-lock)

For more information see pi alias.