Is there any way to disable the rank order in rundeck? - rundeck

I have nodes abcd1,abcd2,abcd3,abcd4
Input = abcd1,abcd3,abcd4,abcd2
If the rank order ascending - execution follows- abcd1,abcd2,abcd3,abcd4 order
IF the rank order descending - execution follows -abcd4,abcd3,abcd2,abcd1 order
.
I want my executions to follow same order as input i.e, abcd1,abcd3,abcd4,abcd2 . How can this be achieved?

You can use the "Rank Attribute" option on your job definition, for that, just define (or use) some attribute on your node source and Rundeck use it, for example, using this resources.xml (check myorder custom attribute):
<?xml version="1.0" encoding="UTF-8"?>
<project>
<node name="node00" description="Node 00" tags="" myorder="02" hostname="192.168.33.20" osArch="amd64" osFamily="unix" osName="Linux" osVersion="3.10.0-1062.4.1.el7.x86_64" username="vagrant" ssh-key-storage-path="keys/rundeck"/>
<node name="node01" description="Node 01" tags="" myorder="03" hostname="192.168.33.21" osArch="amd64" osFamily="unix" osName="Linux" osVersion="3.10.0-1062.4.1.el7.x86_64" username="vagrant" ssh-key-storage-path="keys/rundeck"/>
<node name="node02" description="Node 02" tags="" myorder="01" hostname="192.168.33.22" osArch="amd64" osFamily="unix" osName="Linux" osVersion="3.10.0-1062.4.1.el7.x86_64" username="vagrant" ssh-key-storage-path="keys/rundeck"/>
</project>
Now set set "Rank Attribute" textbox with myorder attribute, save the job and run again. You can see the order based on that attribute.
More information here.
UPDATE 30/07/2020:
Following the first comment of this answer, exist a way to modify the resource.xml file with a bash script, later update the node definition and later launch the child job to new rankAttribute order using Job Reference Step.
First, the script that changes the Rundeck Model Source (needs xmlstarlet):
#!/bin/bash
path=$RD_OPTION_PATH
myorder=$RD_OPTION_NODE_ORDER
counter=1
Field_Separator=$IFS
# set comma as internal field separator for the string list
IFS=,
for value in $myorder;
do
echo $counter
xmlstarlet ed --inplace -u "/project/node[$counter][#myorder]/#myorder" -v $value $path
counter=$((counter+1))
done
IFS=$Field_Separator
Now, the Parent Job (that calls the script above, refresh the Rundeck Model Source and finally launch the "target" job):
<joblist>
<job>
<context>
<options preserveOrder='true'>
<option name='node_order' value='3,2,1' />
<option name='path' required='true' value='/home/m68k/Rundeck/resources/farm.xml' />
</options>
</context>
<defaultTab>nodes</defaultTab>
<description></description>
<executionEnabled>true</executionEnabled>
<id>860e7189-f399-47c4-ab86-5b47017188dd</id>
<loglevel>INFO</loglevel>
<name>Parent</name>
<nodeFilterEditable>true</nodeFilterEditable>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='sequential'>
<command>
<description>Just a message</description>
<exec>echo "Starting..."</exec>
</command>
<command>
<description>Call the script</description>
<fileExtension>.sh</fileExtension>
<scriptargs />
<scriptfile>/home/m68k/Downloads/TEST.sh</scriptfile>
<scriptinterpreter>/bin/bash</scriptinterpreter>
</command>
<command>
<description>Refresh Rundeck Model Source</description>
<step-plugin type='source-refresh-plugin'>
<configuration>
<entry key='sleep' value='5' />
</configuration>
</step-plugin>
</command>
<command>
<description>And launch the "target" job against the new node order</description>
<jobref name='Child' nodeStep='true'>
<uuid>0e02890e-c9dd-4a65-ace1-bfe90b9b7a8e</uuid>
</jobref>
</command>
</sequence>
<uuid>860e7189-f399-47c4-ab86-5b47017188dd</uuid>
</job>
</joblist>
And finally, the Child Job, the "target job".
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<dispatch>
<excludePrecedence>true</excludePrecedence>
<keepgoing>false</keepgoing>
<rankAttribute>myorder</rankAttribute>
<rankOrder>ascending</rankOrder>
<successOnEmptyNodeFilter>false</successOnEmptyNodeFilter>
<threadcount>1</threadcount>
</dispatch>
<executionEnabled>true</executionEnabled>
<id>0e02890e-c9dd-4a65-ace1-bfe90b9b7a8e</id>
<loglevel>INFO</loglevel>
<name>Child</name>
<nodeFilterEditable>false</nodeFilterEditable>
<nodefilters>
<filter>node.*</filter>
</nodefilters>
<nodesSelectedByDefault>true</nodesSelectedByDefault>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>echo "Hello ${node.name}"</exec>
</command>
</sequence>
<uuid>0e02890e-c9dd-4a65-ace1-bfe90b9b7a8e</uuid>
</job>
</joblist>
So, if you set 3,1,2 order, you can see the result on myorder attribute on resources.xml file and the child job executes on that order.
<?xml version="1.0"?>
<project>
<node name="node00" description="Node 00" tags="" hostname="192.168.33.20" osArch="amd64" osFamily="unix" osName="Linux" osVersion="3.10.0-1062.4.1.el7.x86_64" username="vagrant" ssh-key-storage-path="keys/rundeck" myorder="3"/>
<node name="node01" description="Node 01" tags="" hostname="192.168.33.21" osArch="amd64" osFamily="unix" osName="Linux" osVersion="3.10.0-1062.4.1.el7.x86_64" username="vagrant" ssh-key-storage-path="keys/rundeck" myorder="1"/>
<node name="node02" description="Node 02" tags="" hostname="192.168.33.22" osArch="amd64" osFamily="unix" osName="Linux" osVersion="3.10.0-1062.4.1.el7.x86_64" username="vagrant" ssh-key-storage-path="keys/rundeck" myorder="2"/>
</project>

Related

Nodes not displaying, console shows xml parsing error

I'm having troubles viewing my nodes in a fresh rundeck install. resources.xml
<?xml version="1.0" encoding="UTF-8"?>
<project>
<node name="fooweb01"
description="fooweb01" tags="foo,us-east,webserver"
osFamily="unix" osName="Linux"
hostname="fooweb01" username="user"
/>
<node name="fooweb02"
description="fooweb02" tags="foo,us-east,webserver"
osFamily="unix" osName="Linux"
hostname="fooweb02" username="user"
/>
<node name="fooweb03"
description="fooweb03" tags="foo,us-east,webserver"
osFamily="unix" osName="Linux"
hostname="fooweb03" username="user"
/>
<node name="fooweb04"
description="fooweb04" tags="foo,us-east,webserver"
osFamily="unix" osName="Linux"
hostname="fooweb04" username="user"
/>
<node name="foocorp01"
description="foocorp01" tags="foo,us-east,corporate"
osFamily="unix" osName="Linux"
hostname="foocorp01" username="user"
/>
<node name="foocorp02"
description="foocorp02" tags="foo,us-east,corporate"
osFamily="unix" osName="Linux"
hostname="foocorp02" username="user"
/>
<node name="foopartner01"
description="foopartner01" tags="foo,us-east,partner-api"
osFamily="unix" osName="Linux"
hostname="foopartner01" username="user"
/>
<node name="foodb01"
description="foodb01" tags="foo,us-east,cluster-node"
osFamily="unix" osName="Linux"
hostname="foodb01" username="user"
/>
<node name="foodb02"
description="foodb02" tags="foo,us-east,cluster-node"
osFamily="unix" osName="Linux"
hostname="foodb02" username="user"
/>
<node name="foodb03"
description="foodb03" tags="foo,us-east,cluster-node"
osFamily="unix" osName="Linux"
hostname="foodb03" username="user"
/>
<node name="foolb01"
description="foolb03" tags="foo,us-east,haproxy"
osFamily="unix" osName="Linux"
hostname="foolb03" username="user"
/>
<node name="foolb02"
description="foolb03" tags="foo,us-east,haproxy"
osFamily="unix" osName="Linux"
hostname="foolb03" username="user"
/>
<node name="foojobs01"
description="foojobs03" tags="foo,us-east,docker-services"
osFamily="unix" osName="Linux"
hostname="foojobs03" username="user"
/>
<node name="foomonitor"
description="Ops Host" tags="foo,us-east,monitor"
osFamily="unix" osName="Linux"
hostname="foomonitor" username="user"
/>
</project>
project.properties in the same folder
project.resources.file=/var/lib/rundeck/projects/cron_jobs/etc/resources.xml
resources.source.1.type=file
resources.source.1.config.file=/var/lib/rundeck/projects/cron_jobs/etc/resources.xml
resources.source.1.config.format=resourcexml
resources.source.1.config.requireFileExists=true
resources.source.1.config.includeServerNode=true
resources.source.1.config.generateFileAutomatically=true
project.resources.file=/var/lib/rundeck/projects/cron_jobs/etc/resources.xml was a recent test that didn't help. When i load project/cron_jobs/nodes in the browser console i see
XML Parsing Error: syntax error
Location: https://example.org/project/cron_jobs/nodes
Line Number 1: Column 1:
There are no errors in the logs, i have reimported the project each time i make a change to the file, which has not been frequent.
This is driving me crazy, looking for another pair of eyes. All other pages work fine.
Rundeck enumerates their model sources (for example: 1=your resources.xml file, 2=ansible inventory, 3=ec2 nodes, etc.) in your case, the first one is the resources.xml file.
Just delete the project.resources.file=/var/lib/rundeck/projects/cron_jobs/etc/resources.xml line and save.
I created a new project (on Rundeck 3.3.10), deleted the first model source (local), added your resources.xml file (which works like a charm) as first model source and the project.properties looks in the following way:
#Fri Mar 26 08:53:10 CLST 2021
#edit below
project.disable.executions=false
project.disable.schedule=false
project.execution.history.cleanup.batch=500
project.execution.history.cleanup.enabled=false
project.execution.history.cleanup.retention.days=60
project.execution.history.cleanup.retention.minimum=50
project.execution.history.cleanup.schedule=0 0 0 1/1 * ? *
project.jobs.gui.groupExpandLevel=1
project.name=ProjectEXAMPLE
project.nodeCache.enabled=true
project.nodeCache.firstLoadSynch=true
project.output.allowUnsanitized=false
project.ssh-authentication=privateKey
project.ssh-command-timeout=0
project.ssh-connect-timeout=0
project.ssh-keypath=/home/user/.ssh/id_rsa
resources.source.1.config.file=/path/to/your/resources.xml
resources.source.1.config.format=resourcexml
resources.source.1.config.generateFileAutomatically=true
resources.source.1.config.writeable=true
resources.source.1.type=file
service.FileCopier.default.provider=jsch-scp
service.NodeExecutor.default.provider=jsch-ssh
And the nodes on "Nodes" page.

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>

Is there an option to specify multiple user names for remote execution on the same node?

Is there anyway i can access the same node via 2 different users (appuser,webuser) to execute scripts?
Will it be ambiguous if there is another entry made for the same node with different username?
test1:
hostname: "10.35.20.76"
nodename: "test1"
osArch: "x86"
osFamily: "unix"
osName: "Solaris"
osVersion: "11.4"
tags: "TEST"
username: "appuser"
A good option to do that is to use a job option pointing to your resources file, in this way:
Job Definition example:
<joblist>
<job>
<context>
<options preserveOrder='true'>
<option name='opt1' value='vagrant' />
</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>eaf3f18e-97c0-4c85-b2fd-9a0b8dd8696e</id>
<loglevel>INFO</loglevel>
<name>HelloWorld</name>
<nodeFilterEditable>false</nodeFilterEditable>
<nodefilters>
<filter>name: node00</filter>
</nodefilters>
<nodesSelectedByDefault>true</nodesSelectedByDefault>
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<exec>echo "done"</exec>
</command>
</sequence>
<uuid>eaf3f18e-97c0-4c85-b2fd-9a0b8dd8696e</uuid>
</job>
</joblist>
Resources.xml example (check the "username" attribute):
<?xml version="1.0" encoding="UTF-8"?>
<project>
<node name="mylocalhost" description="Rundeck server node" tags="" hostname="mylocalhost" osArch="amd64" osFamily="unix" osName="Linux" osVersion="5.15.0-66-generic" username="jdoe"/>
<node name="node00" description="Node 00" tags="" hostname="192.168.33.20" osArch="amd64" osFamily="unix" osName="Linux" osVersion="4.10.0-1062.4.1.el7.x86_64" username="${option.opt1}" ssh-key-storage-path="keys/rundeck"/>
</project>
Also, you can do the same using passwords. Take a look at this.

Is there a way to use login/password of login account to reuse in a playbook?

I have created a job with 2 options for the user writes his login/password. This credentials will be used later in a playbook as extra-variables.
But all this credentials are readable in logs !!!
How to workaround that ?
You can use the "Mask Password" Log filter in your inline-playbook or your playbook steps (also, for any Rundeck step), you can check the documentation here. I did a Job Definition example that works:
<joblist>
<job>
<context>
<options preserveOrder='true'>
<option name='opt1' secure='true' value='12345' valueExposed='true' />
</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>2c9b3903-a545-4dbd-aeac-578889dbb611</id>
<loglevel>INFO</loglevel>
<name>HelloWorld</name>
<nodeFilterEditable>false</nodeFilterEditable>
<nodefilters>
<filter>name: 192.168.33.20</filter>
</nodefilters>
<nodesSelectedByDefault>true</nodesSelectedByDefault>
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<node-step-plugin type='com.batix.rundeck.plugins.AnsiblePlaybookInlineWorkflowNodeStep'>
<configuration>
<entry key='ansible-base-dir-path' value='/home/user/' />
<entry key='ansible-become' value='false' />
<entry key='ansible-playbook-inline' value='---
# This playbook prints a simple debug message
- name: Echo
hosts: all
connection: local
tasks:
- name: Print debug message
debug:
msg: ${option.opt1}' />
<entry key='ansible-ssh-passphrase-option' value='option.password' />
<entry key='ansible-ssh-use-agent' value='false' />
</configuration>
</node-step-plugin>
<plugins>
<LogFilter type='LogFilter:mask-passwords'>
<config>
<color>red</color>
<replacement>[SECURE]</replacement>
</config>
</LogFilter>
</plugins>
</command>
</sequence>
<uuid>2c9b3903-a545-4dbd-aeac-578889dbb611</uuid>
</job>
</joblist>

rundeck pass output from job(step) one to job(step) two

In rundeck, I have two selections, selection1 and selection2 which will be executed on node1 and node2 respectively. Slection2 's input is from output of selections. How can I make it ? with two jobs or two steps? and How to pass the arguments.
You can pass options between jobs using Job Reference Step and arguments. I leave an example with two jobs: JobA and JobB, the JobA just print an option and the JobB that call the JobA and pass their option to JobA option through argument.
Job A:
<joblist>
<job>
<context>
<options preserveOrder="true">
<option name="opta" />
</options>
</context>
<defaultTab>nodes</defaultTab>
<description />
<executionEnabled>true</executionEnabled>
<id>6d64bd33-71de-4d20-8bcd-c65785603b23</id>
<loglevel>INFO</loglevel>
<name>JobA</name>
<nodeFilterEditable>false</nodeFilterEditable>
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing="false" strategy="node-first">
<command>
<exec>echo ${option.opta}</exec>
</command>
</sequence>
<uuid>6d64bd33-71de-4d20-8bcd-c65785603b23</uuid>
</job>
</joblist>
Job B:
<joblist>
<job>
<context>
<options preserveOrder="true">
<option name="optb" />
</options>
</context>
<defaultTab>nodes</defaultTab>
<description />
<executionEnabled>true</executionEnabled>
<id>22d0e6cc-e0f3-48e5-b8a5-3007e448ae18</id>
<loglevel>INFO</loglevel>
<name>JobB</name>
<nodeFilterEditable>false</nodeFilterEditable>
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing="false" strategy="node-first">
<command>
<jobref name="JobA" nodeStep="true">
<arg line="-opta ${option.optb}" />
<uuid>6d64bd33-71de-4d20-8bcd-c65785603b23</uuid>
</jobref>
</command>
</sequence>
<uuid>22d0e6cc-e0f3-48e5-b8a5-3007e448ae18</uuid>
</job>
</joblist>
Also, you can capture some output and pass this data using arguments between jobs. I leave another Example:
Job A (just print an option):
<joblist>
<job>
<context>
<options preserveOrder="true">
<option name="opta" />
</options>
</context>
<defaultTab>nodes</defaultTab>
<description />
<executionEnabled>true</executionEnabled>
<id>6d64bd33-71de-4d20-8bcd-c65785603b23</id>
<loglevel>INFO</loglevel>
<name>JobA</name>
<nodeFilterEditable>false</nodeFilterEditable>
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing="false" strategy="node-first">
<command>
<exec>echo ${option.opta}</exec>
</command>
</sequence>
<uuid>6d64bd33-71de-4d20-8bcd-c65785603b23</uuid>
</job>
</joblist>
Job B (it generates data, store at ${data.USER} variable and call the JobA to pass that variable as an argument using Job Reference Step):
<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>
<jobref name="JobA" nodeStep="true">
<arg line="-opta ${data.USER}" />
<uuid>6d64bd33-71de-4d20-8bcd-c65785603b23</uuid>
</jobref>
</command>
<pluginConfig>
<LogFilter type="key-value-data">
<config>
<logData>true</logData>
<regex>^(USER)\s*=\s*(.+)$</regex>
</config>
</LogFilter>
</pluginConfig>
</sequence>
<uuid>a0daf1e3-e918-43dc-b232-bc46a7a287b6</uuid>
</job>
</joblist>
You can see a very useful example here.