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.
Related
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.
I use Rundeck to execute the Job A. In Job A, I have a Global Log Filter that captures key/value data using the default regex (RUNDECK:DATA:...).
I call another job - Job B - that prints stuff starting with RUNDECK:DATA:key = value. I execute Job B from Job A. Somehow the Global Log Filter that I setup in Job A doesn't parse the output of Job B.
I added the same Global Log Filter to Job B, and see that the data is captured correctly, but it is not available on Job A so that it can be used on the following steps.
Does anyone know if it is possible to capture key/value from the output of a another job? I managed to capture values from steps of the same job, but not when the output comes from an execution of another called job.
Checking your last comment the easiest way to do that is to use a file that stores the value (on JobB) and later is processed by the JobA next steps. Basically the JobA launches JobB via Job Reference Step, then JobB generates the data on a file, and the JobA recovers that value from the temporal file on the next steps.
JobA:
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<executionEnabled>true</executionEnabled>
<id>a0daf1e3-e918-43dc-b232-bc46a7a287b6</id>
<loglevel>INFO</loglevel>
<name>JobA</name>
<nodeFilterEditable>false</nodeFilterEditable>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>echo "starting Job A"</exec>
</command>
<command>
<description>Job B call that geneates the temp value</description>
<jobref name='JobB' nodeStep='true'>
<uuid>ba183d3b-67d9-4499-b863-da8b7ac8aef3</uuid>
</jobref>
</command>
<command>
<exec>echo "printing the Job B value"</exec>
</command>
<command>
<exec>cat tempfile.txt</exec>
<plugins>
<LogFilter type='key-value-data'>
<config>
<invalidKeyPattern>\s|\$|\{|\}|\\</invalidKeyPattern>
<logData>true</logData>
<regex>^(mykey)\s*=\s*(.+)$</regex>
</config>
</LogFilter>
</plugins>
</command>
<command>
<exec>echo "the value is ${data.mykey}"</exec>
</command>
</sequence>
<uuid>a0daf1e3-e918-43dc-b232-bc46a7a287b6</uuid>
</job>
</joblist>
JobB:
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<executionEnabled>true</executionEnabled>
<id>ba183d3b-67d9-4499-b863-da8b7ac8aef3</id>
<loglevel>INFO</loglevel>
<name>JobB</name>
<nodeFilterEditable>false</nodeFilterEditable>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>echo "Generating the value..."</exec>
</command>
<command>
<exec>echo "mykey=myvalue" > tempfile.txt</exec>
</command>
<command>
<exec>echo "Value generated on temp file"</exec>
</command>
</sequence>
<uuid>ba183d3b-67d9-4499-b863-da8b7ac8aef3</uuid>
</job>
</joblist>
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.
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.
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).