Scripting Tasks

Last modified 29 Aug 2024 13:54 +02:00

There are two ways of executing scripts within tasks:

  1. traditional one, where the whole script is put into the task;

  2. iterative one, where the search for objects is executed by generic iterative task handler and the script contains only the actions that are to be executed on objects found.

Iterative execution is available since midPoint 3.8. Its main advantage is that it is segmentable, so the task can be distributed onto multiple nodes as well as suspended + resumed at the (approximate) point of suspension.

Iterative execution has also some performance (memory consumption) advantages when large number of objects are processed. Therefore, for considerable number of objects (e.g. thousands) the traditional tasks are considered to be deprecated.

Traditional scripting tasks

An example

Traditional action that sets preferredLanguage for all users

Git

<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Copyright (c) 2010-2024 Evolveum
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~     http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->
<task xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
      xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
      xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
      xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
      xmlns:s="http://midpoint.evolveum.com/xml/ns/public/model/scripting-3"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <name>Set preferredLanguage for all users</name>
    <ownerRef oid="00000000-0000-0000-0000-000000000002"/>
    <executionState>runnable</executionState>
    <schedule>
        <recurrence>single</recurrence>
    </schedule>
    <activity>
        <work>
            <nonIterativeScripting>
                <scriptExecutionRequest>
                    <s:search>
                        <s:type>UserType</s:type>
                        <s:action>
                            <s:type>modify</s:type>
                            <s:parameter>
                                <s:name>delta</s:name>
                                <c:value xsi:type="t:ObjectDeltaType">
                                    <t:changeType>modify</t:changeType>
                                    <t:objectType>UserType</t:objectType>
                                    <t:itemDelta>
                                        <t:modificationType>replace</t:modificationType>
                                        <t:path>c:preferredLanguage</t:path>
                                        <t:value>sk_SK</t:value>
                                    </t:itemDelta>
                                </c:value>
                            </s:parameter>
                        </s:action>
                    </s:search>
                </scriptExecutionRequest>
            </nonIterativeScripting>
        </work>
    </activity>
</task>

This is a traditional approach: the whole script is present in the nonIterativeScripting property. The script consists of search instruction, followed by the modify action.

This approach is more general than the following one: the script can be of any form, not necessarily search + something. However, the work cannot be segmented into buckets, and therefore cannot be distributed nor resumed after suspension.

Iterative scripting tasks

An example (single-node)

Iterative action that sets preferredLanguage for all users

Git

<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Copyright (c) 2010-2024 Evolveum
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~     http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->
<task xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
      xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
      xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
      xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
      xmlns:s="http://midpoint.evolveum.com/xml/ns/public/model/scripting-3"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <name>Set preferredLanguage for all users (singlenode)</name>
    <ownerRef oid="00000000-0000-0000-0000-000000000002"/>
    <executionState>runnable</executionState>
    <schedule>
        <recurrence>single</recurrence>
    </schedule>
    <activity>
        <work>
            <iterativeScripting>
                <objects>
                    <type>UserType</type>
                </objects>
                <scriptExecutionRequest>
                    <s:action>
                        <s:type>modify</s:type>
                        <s:parameter>
                            <s:name>delta</s:name>
                            <c:value xsi:type="t:ObjectDeltaType">
                                <t:changeType>modify</t:changeType>
                                <t:objectType>UserType</t:objectType>
                                <t:itemDelta>
                                    <t:modificationType>replace</t:modificationType>
                                    <t:path>c:preferredLanguage</t:path>
                                    <t:value>sk_SK</t:value>
                                </t:itemDelta>
                            </c:value>
                        </s:parameter>
                    </s:action>
                </scriptExecutionRequest>
            </iterativeScripting>
        </work>
    </activity>
</task>

Now the scriptExecutionRequest contains only the action(s) to be executed on objects found. The objects to be processed are specified using objects and (optionally) query properties.

Although this approach is more limited (it is always a search followed by some processing), it can be easily segmented and thus distributed and resumed after suspension.

An example of distribution on cluster nodes is shown below:

An example (multi-node)

Iterative action that sets preferredLanguage for all users (multi-node)

Git

<!--
  ~ Copyright (c) 2010-2021 Evolveum
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~     http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->

<task xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
      xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
      xmlns:s="http://midpoint.evolveum.com/xml/ns/public/model/scripting-3"
      xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <name>Set preferredLanguage for all users (multinode)</name>
    <ownerRef oid="00000000-0000-0000-0000-000000000002"/>
    <executionState>runnable</executionState>
    <activity>
        <work>
            <iterativeScripting>
                <objects>
                    <type>UserType</type>
                </objects>
                <scriptExecutionRequest>
                    <s:action>
                        <s:type>modify</s:type>
                        <s:parameter>
                            <s:name>delta</s:name>
                            <c:value xsi:type="t:ObjectDeltaType">
                                <t:itemDelta>
                                    <t:modificationType>replace</t:modificationType>
                                    <t:path>c:preferredLanguage</t:path>
                                    <t:value>sk_SK</t:value>
                                </t:itemDelta>
                            </c:value>
                        </s:parameter>
                    </s:action>
                </scriptExecutionRequest>
            </iterativeScripting>
        </work>
        <distribution>
            <buckets>
                <oidSegmentation>
                    <depth>3</depth>
                </oidSegmentation>
            </buckets>
            <workers>
                <workersPerNode>
                    <count>2</count>
                </workersPerNode>
            </workers>
        </distribution>
    </activity>
</task>

Here the work to be done is segmented into 163 = 4096 buckets that are processed by two worker tasks on each node. (This number of buckets is appropriate for - let’s say - 40.000-400.000 users, having 100-1000 users in one bucket.)

Was this page helpful?
YES NO
Thanks for your feedback