Run pool of jobs in parallel, each job only executing once - rundeck

I have a (powershell, if it matters) script I want to run once for each state. The job takes a variable amount of time per state (and not based on state population or anything like that, not predictable), so what I'd like to do is create a flow with the 50 jobs as steps, and then tell Rundeck to run those 50 jobs in 5 threads. Maybe 10 per thread, but probably not as some of them are faster than others; but let Rundeck manage that, so if it ends up being 8-9-12-10-11 that particular time, great. I understand how to use the Rundeck API to create those 50 steps and add them to a workflow.
I can't seem to see how Rundeck would manage this exactly how I want, however. The strategies for workflows seem to all assume you want to run all of the jobs on all of the nodes (meaning, if I have 50 steps and 5 nodes, it would run 250 total things, each state 5 times) - I don't want that; I want each job to run only on one node, but I don't care which node that is - whatever node is free. Just act as a load balancer, basically.
Does Rundeck support this, or would I have to build my own load balancing script?

I did an example using three nodes, three jobs, and a parent job to dispatch these three jobs to each node (once) via Job Reference Step.
First, the Parent job which calls the child jobs using a parallel strategy which means any step (each job reference) runs at the same time, orchestrator as "random subset" of a set of nodes (three on my example) and "count" set as "1" (each job reference step to a single node).
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<dispatch>
<excludePrecedence>true</excludePrecedence>
<keepgoing>false</keepgoing>
<rankOrder>ascending</rankOrder>
<successOnEmptyNodeFilter>false</successOnEmptyNodeFilter>
<threadcount>3</threadcount>
</dispatch>
<executionEnabled>true</executionEnabled>
<id>17aad193-1e2c-45dc-b736-901c1de00954</id>
<loglevel>INFO</loglevel>
<name>ParentJobRemoteParallel</name>
<nodeFilterEditable>false</nodeFilterEditable>
<nodefilters>
<filter>node.*</filter>
</nodefilters>
<nodesSelectedByDefault>true</nodesSelectedByDefault>
<orchestrator>
<configuration>
<count>3</count>
</configuration>
<type>subset</type>
</orchestrator>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='parallel'>
<command>
<jobref name='HelloWorldONE' nodeStep='true'>
<uuid>e1ec6d2c-62d9-4de4-af6d-7e03f59cc4e5</uuid>
</jobref>
</command>
<command>
<jobref name='HelloWorldTWO' nodeStep='true'>
<uuid>a57e74f2-050d-4a13-841a-3a4552d8227b</uuid>
</jobref>
</command>
<command>
<jobref name='HelloWorldTHREE' nodeStep='true'>
<uuid>47067c03-da25-43e1-83cc-9fe0492f0797</uuid>
</jobref>
</command>
</sequence>
<uuid>17aad193-1e2c-45dc-b736-901c1de00954</uuid>
</job>
</joblist>
Now the Child Jobs, these jobs are configured pointed to a set of nodes with random subset orchestrator and "1", similar to Parent Job.
HelloWorldONE:
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<dispatch>
<excludePrecedence>true</excludePrecedence>
<keepgoing>false</keepgoing>
<rankOrder>ascending</rankOrder>
<successOnEmptyNodeFilter>true</successOnEmptyNodeFilter>
<threadcount>1</threadcount>
</dispatch>
<executionEnabled>true</executionEnabled>
<id>e1ec6d2c-62d9-4de4-af6d-7e03f59cc4e5</id>
<loglevel>INFO</loglevel>
<name>HelloWorldONE</name>
<nodeFilterEditable>false</nodeFilterEditable>
<nodefilters>
<filter>node.*</filter>
</nodefilters>
<nodesSelectedByDefault>true</nodesSelectedByDefault>
<orchestrator>
<configuration>
<count>1</count>
</configuration>
<type>subset</type>
</orchestrator>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>echo "i am the first job"</exec>
</command>
</sequence>
<uuid>e1ec6d2c-62d9-4de4-af6d-7e03f59cc4e5</uuid>
</job>
</joblist>
HelloWorldTWO:
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<dispatch>
<excludePrecedence>true</excludePrecedence>
<keepgoing>false</keepgoing>
<rankOrder>ascending</rankOrder>
<successOnEmptyNodeFilter>false</successOnEmptyNodeFilter>
<threadcount>1</threadcount>
</dispatch>
<executionEnabled>true</executionEnabled>
<id>a57e74f2-050d-4a13-841a-3a4552d8227b</id>
<loglevel>INFO</loglevel>
<name>HelloWorldTWO</name>
<nodeFilterEditable>false</nodeFilterEditable>
<nodefilters>
<filter>node.*</filter>
</nodefilters>
<nodesSelectedByDefault>true</nodesSelectedByDefault>
<orchestrator>
<configuration>
<count>1</count>
</configuration>
<type>subset</type>
</orchestrator>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='sequential'>
<command>
<exec>echo "i am the second job"</exec>
</command>
</sequence>
<uuid>a57e74f2-050d-4a13-841a-3a4552d8227b</uuid>
</job>
</joblist>
HelloWorldTHREE:
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<dispatch>
<excludePrecedence>true</excludePrecedence>
<keepgoing>false</keepgoing>
<rankOrder>ascending</rankOrder>
<successOnEmptyNodeFilter>false</successOnEmptyNodeFilter>
<threadcount>1</threadcount>
</dispatch>
<executionEnabled>true</executionEnabled>
<id>47067c03-da25-43e1-83cc-9fe0492f0797</id>
<loglevel>INFO</loglevel>
<name>HelloWorldTHREE</name>
<nodeFilterEditable>false</nodeFilterEditable>
<nodefilters>
<filter>node.*</filter>
</nodefilters>
<nodesSelectedByDefault>true</nodesSelectedByDefault>
<orchestrator>
<configuration>
<count>1</count>
</configuration>
<type>subset</type>
</orchestrator>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>echo "i am the third job"</exec>
</command>
</sequence>
<uuid>47067c03-da25-43e1-83cc-9fe0492f0797</uuid>
</job>
</joblist>
Here you can see the result.
This is also appliable to steps, job reference steps are steps like a command step or script-step.

Related

is there any way for rundeck opensource to trigger jobs at failed workflow step?

Do we have any plugin or is there any way to allow the jobs to resume execution at failed workflow step?
If my job 1 and job 2 got passed, then job 3 have to trigger.If job 1 got passed and job 2 got failed and when we fix it for job 2 and triggered it manually and if it got passes, then job 3 should know the job 2 got passes and job 1 previous state is passed.then job3 should automatically trigger. Do we have any plugin or a way to do this for rundeck opensource?
The best approach is to attach an error handler on your step (in your case job reference step), that error handler calls another job, I leave a basic example:
RemediationJob (the job that must be called if any ParentJob job reference fails through error handler):
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<executionEnabled>true</executionEnabled>
<id>67c56627-9dbd-4ad2-b6c1-04436ab3d0b2</id>
<loglevel>INFO</loglevel>
<name>RemediationJob</name>
<nodeFilterEditable>false</nodeFilterEditable>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<fileExtension>.sh</fileExtension>
<script><![CDATA[echo "fixing..."
echo "fixed! try run the job again"]]></script>
<scriptargs />
<scriptinterpreter>/bin/bash</scriptinterpreter>
</command>
</sequence>
<uuid>67c56627-9dbd-4ad2-b6c1-04436ab3d0b2</uuid>
</job>
</joblist>
JobA:
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<executionEnabled>true</executionEnabled>
<id>5d19ea42-0431-4a68-a061-623f498222f6</id>
<loglevel>INFO</loglevel>
<name>ChildA</name>
<nodeFilterEditable>false</nodeFilterEditable>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>echo "hi"</exec>
</command>
</sequence>
<uuid>5d19ea42-0431-4a68-a061-623f498222f6</uuid>
</job>
</joblist>
JobB (with an intentional error on the step):
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<executionEnabled>true</executionEnabled>
<id>00f5aaa5-5726-4f65-86a3-2a3c404bff08</id>
<loglevel>INFO</loglevel>
<name>ChildB</name>
<nodeFilterEditable>false</nodeFilterEditable>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>eco "hi"</exec>
</command>
</sequence>
<uuid>00f5aaa5-5726-4f65-86a3-2a3c404bff08</uuid>
</job>
</joblist>
ParentJob (which calls JobA and JobB and uses error handler on any job reference step)
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<executionEnabled>true</executionEnabled>
<id>c2e0a05e-4fdd-4c33-9b4e-c9109d3667c6</id>
<loglevel>INFO</loglevel>
<name>ParentJob</name>
<nodeFilterEditable>false</nodeFilterEditable>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<errorhandler>
<jobref name='RemediationJob' nodeStep='true'>
<uuid>67c56627-9dbd-4ad2-b6c1-04436ab3d0b2</uuid>
</jobref>
</errorhandler>
<jobref name='ChildA' nodeStep='true'>
<uuid>5d19ea42-0431-4a68-a061-623f498222f6</uuid>
</jobref>
</command>
<command>
<errorhandler>
<jobref name='RemediationJob' nodeStep='true'>
<uuid>67c56627-9dbd-4ad2-b6c1-04436ab3d0b2</uuid>
</jobref>
</errorhandler>
<jobref name='ChildB' nodeStep='true'>
<uuid>00f5aaa5-5726-4f65-86a3-2a3c404bff08</uuid>
</jobref>
</command>
</sequence>
<uuid>c2e0a05e-4fdd-4c33-9b4e-c9109d3667c6</uuid>
</job>
</joblist>
In this example, the second job reference always fails intentionally, in that way you can see how to trigger another job if the step (job reference step in your case) fails.

Is there any option to kill a job running for longer time on remote machine by rundeck itself?

I need to kill a rundeck job by itself when the job runs more than 2hours on remote machine,is there a possibility
You can set a timeout value in "Timeout" textbox (When creating or editing your job go to the "Other" tab an see that option, check this. You can use values in seconds (like 10s), minutes (like 5m), hours (like 2h), or days (like 2d), also, you can pass an option defined with that value.
I leave a job definition example to test:
<joblist>
<job>
<context>
<options preserveOrder='true'>
<option name='timeout' value='5s' />
</options>
</context>
<defaultTab>nodes</defaultTab>
<description></description>
<dispatch>
<excludePrecedence>true</excludePrecedence>
<keepgoing>false</keepgoing>
<rankOrder>ascending</rankOrder>
<successOnEmptyNodeFilter>false</successOnEmptyNodeFilter>
<threadcount>1</threadcount>
</dispatch>
<executionEnabled>true</executionEnabled>
<id>13ba3f6b-f921-4ab5-95ba-56eb335eed4b</id>
<loglevel>INFO</loglevel>
<name>HugeDelay</name>
<nodeFilterEditable>false</nodeFilterEditable>
<nodefilters>
<filter>name: node01</filter>
</nodefilters>
<nodesSelectedByDefault>true</nodesSelectedByDefault>
<plugins />
<schedule>
<month month='*' />
<time hour='13' minute='19' seconds='0' />
<weekday day='*' />
<year year='*' />
</schedule>
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>sleep 30; echo "hi"</exec>
</command>
</sequence>
<timeout>${option.timeout}</timeout>
<uuid>13ba3f6b-f921-4ab5-95ba-56eb335eed4b</uuid>
</job>
</joblist>

my rundeck job is not letting me pass all the parameters, just one, and I need all

I use this but only get a SINGLE PARAMETER, passed to the rundeck job:
... ${option.ticketnumber} ...
I want ALL the parameters (not just ONE) so that I can parse them within my code
free and CLEAR of Rundeck.
Anyone want to comment out there?
You can wrap your steps using key/value data with a regex to generate a set of data variables like this to use in your workflow (in this way you avoid to define individual options to pass later). Here a job definition example:
The job that generates the data values:
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description>Regex and data passing demo.</description>
<executionEnabled>true</executionEnabled>
<id>a0daf1e3-e918-43dc-b232-bc46a7a287b6</id>
<loglevel>INFO</loglevel>
<name>Regex</name>
<nodeFilterEditable>false</nodeFilterEditable>
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>env</exec>
</command>
<command>
<exec>echo ${data.SHELL}</exec>
</command>
<command>
<exec>echo ${data.USER}</exec>
</command>
<command>
<exec>echo ${data.PWD}</exec>
</command>
<command>
<jobref name='AnotherJob' nodeStep='true'>
<arg line='-option1 ${data.USER}' />
<uuid>4932f9c7-a435-4332-8b1a-5ade41da9edd</uuid>
</jobref>
</command>
<pluginConfig>
<LogFilter type='key-value-data'>
<config>
<logData>true</logData>
<regex>^(SHELL|USER|PWD)\s*=\s*(.+)$</regex>
</config>
</LogFilter>
</pluginConfig>
</sequence>
<uuid>a0daf1e3-e918-43dc-b232-bc46a7a287b6</uuid>
</job>
</joblist>
The job that gets the data values:
<joblist>
<job>
<context>
<options preserveOrder='true'>
<option name='option1' />
</options>
</context>
<defaultTab>nodes</defaultTab>
<description></description>
<executionEnabled>true</executionEnabled>
<id>4932f9c7-a435-4332-8b1a-5ade41da9edd</id>
<loglevel>INFO</loglevel>
<name>AnotherJob</name>
<nodeFilterEditable>false</nodeFilterEditable>
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>echo "the user from Regex Job is ${option.option1}"</exec>
</command>
</sequence>
<uuid>4932f9c7-a435-4332-8b1a-5ade41da9edd</uuid>
</job>
</joblist>
But to get it (passing) from another job, you need to set individual options using a job reference step with option as arguments.
I programmed around all of this to avoid the restrictions of the interface.

Can rundeck jobs be executed sequentially?

I am migrating a client from Control-M to a more modern solution. Client is running workloads in AWS, and has been considering using Rundeck to replace Control-M.
The control-m jobs run sequentially (one after another) only when the previous jobs terminates successfully.
A few of the jobs run in parallel (1 or more of the parallel jobs do not have dependent "child" jobs), but almost all run sequentially.
Does rundeck support running jobs sequentially? How can this be achieved?
Edit 1: client has over 500 jobs, with one command (shell) each. Target node is ec2 instance in same VPC with ssh public key authn configured.
You can set the Strategy of your Job, for that Create or Edit your job and go to Workflow tab > Strategy = Sequential, check this.
You have a complete explanation of strategies here and here.
EDIT 2: I leave an example focused on jobs using Job Reference Step.
Job A
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<executionEnabled>true</executionEnabled>
<id>7e85b6ff-4813-4f94-85f2-2b91ff359fd4</id>
<loglevel>INFO</loglevel>
<name>JobA</name>
<nodeFilterEditable>false</nodeFilterEditable>
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>sleep 2; echo "i am the job a"</exec>
</command>
</sequence>
<uuid>7e85b6ff-4813-4f94-85f2-2b91ff359fd4</uuid>
</job>
</joblist>
Job B
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<executionEnabled>true</executionEnabled>
<id>859788d6-1fef-4467-8ce9-bc34ef6735e2</id>
<loglevel>INFO</loglevel>
<name>JobB</name>
<nodeFilterEditable>false</nodeFilterEditable>
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>sleep 2; echo "i am the job b"</exec>
</command>
</sequence>
<uuid>859788d6-1fef-4467-8ce9-bc34ef6735e2</uuid>
</job>
</joblist>
Job C
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<executionEnabled>true</executionEnabled>
<id>458d13d1-7436-4d7e-b7a2-382a5bea449f</id>
<loglevel>INFO</loglevel>
<name>JobC</name>
<nodeFilterEditable>false</nodeFilterEditable>
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>sleep 2; echo "i am the job c"</exec>
</command>
</sequence>
<uuid>458d13d1-7436-4d7e-b7a2-382a5bea449f</uuid>
</job>
</joblist>
The parent job with Job Reference Step:
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<executionEnabled>true</executionEnabled>
<id>af4b4937-f4c2-4d73-ba8e-0ccc50bc6479</id>
<loglevel>INFO</loglevel>
<name>ParentJob</name>
<nodeFilterEditable>false</nodeFilterEditable>
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='sequential'>
<command>
<jobref name='JobA' nodeStep='true'>
<uuid>7e85b6ff-4813-4f94-85f2-2b91ff359fd4</uuid>
</jobref>
</command>
<command>
<jobref name='JobB' nodeStep='true'>
<uuid>859788d6-1fef-4467-8ce9-bc34ef6735e2</uuid>
</jobref>
</command>
<command>
<jobref name='JobC' nodeStep='true'>
<uuid>458d13d1-7436-4d7e-b7a2-382a5bea449f</uuid>
</jobref>
</command>
</sequence>
<uuid>af4b4937-f4c2-4d73-ba8e-0ccc50bc6479</uuid>
</job>
</joblist>
For example, if any job fails, the execution stops. With Rundeck 3.2.0 Enterprise, you can use the Job Resume feature to retake the execution at the failed step (only for sequential strategy).

Running a job on multiple nodes in parallel in Rundeck

Is there a possibility that a job can be run in parallel [it has only one task] on all the target nodes [15 nodes precisely]?
Also, will the Thread Count option in rundeck GUI solve the above purpose?
PS: I only have GUI access to Rundeck
You need to dispatch your job to your 15 nodes, and set ThreadCount = 15. I did an example with 3 nodes (node00,node01 and node02) to understand it:
<joblist>
<job>
<defaultTab>summary</defaultTab>
<description></description>
<dispatch>
<excludePrecedence>true</excludePrecedence>
<keepgoing>false</keepgoing>
<rankOrder>ascending</rankOrder>
<successOnEmptyNodeFilter>false</successOnEmptyNodeFilter>
<threadcount>3</threadcount>
</dispatch>
<executionEnabled>true</executionEnabled>
<id>c4a37a41-db35-4a76-b407-be6170c6502d</id>
<loglevel>INFO</loglevel>
<name>JobRemoteParallel</name>
<nodeFilterEditable>false</nodeFilterEditable>
<nodefilters>
<filter>node.*</filter>
</nodefilters>
<nodesSelectedByDefault>true</nodesSelectedByDefault>
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>sleep 2; echo "starting"</exec>
</command>
<command>
<exec>sleep 5; echo "processing"</exec>
</command>
<command>
<exec>echo "done!"</exec>
</command>
</sequence>
<uuid>c4a37a41-db35-4a76-b407-be6170c6502d</uuid>
</job>
</joblist>
Check how works.