How can Rundeck pass a list of machines to the script?

8.9k views Asked by At

I am currently exploring Runddeck to manage several 100 VMs at the time. Rundeck is a very useful tool to run scripts/ commands on multiple machines at the time (each script is passed to the remote machine and then executed locally). However I wonder if there is a way of implementing the following system administation scenario.

Rundeck job requirments (Example: Observium)

  1. "Dispatch to Nodes" option selected but only one target machine selected (Observium machine).
  2. Despite of running the job on only one machine, it would be great if Rundeck allows to select multiple machines, which the script requires. Note, the script is not supposed to be run on all nodes, it's only supposed to be run on a single remote machine but the script requires the list of machines. [How can this be done?]
  3. The script gets access to the list of machines as parameter. [How can this be done?]
  4. If the above is in place, the script then runs on only one machine and iterates through the list of machines ==> For example, it runs /opt/observium/add_device.php v2c @node.name@ ${varSNMPCommunity}

I don't have enough reputation to include images in this post. Please use the link below to see the flow diagram.

https://www.dropbox.com/s/2zt4r9trulpsaqx/RundeckObservium.png?dl=0

4

There are 4 answers

1
Istvan Koncz On BEST ANSWER

if you want to run your script on your rundeck machine and the script will do remote ssh itself to the target machines then you have to select the local machine only in rundeck. Then in the script you can call rundeck to deliver the machine list for the project. e.g. in bash you can do the folowing

#!/bin/bash
projectName="test_project"
nodeFilter="tags:app"
/usr/bin/dispatch -v -p $projectName --filter "$nodeFilter" >/tmp/filtered.node
nodes=( $( grep "hostname" /tmp/filtered.node | cut -f2 -d ":" ) )
echo "$nodes[@]"

The following example will give you the list of those nodes from test_project which have a tag set to app.

0
SaxDaddy On

Rather than have the script run on one node to get a list of machines, try using a node filter to see if you can have RunDeck determine the target nodes from a tag. This will depend on how your project is configured to acquire resources.

For example, if you're using tags then you may want to have a tag that meets your condition. Say you want to find machines that match a tag you created called RebootPending. You can use that as the job's node filter to send a reboot command to those hosts.

Another possible option might be to have your step 2 script output a JSON formatted file to a web server. You can then configure your RD job with an Option that reads this remote URL (a list of host, perhaps) and then take an action based on that list. The job option and node filter can be configured thusly:

Option Name: inputFilter
Description: Used for targeting nodes
Default Value: (empty)
Input Type: [X]Plain text [ ]Secure [ ]Secure Remote Authentication
Allowed Values: [ ]List  [X]Remote URL

Node Filter: tags:${option:inputFilter}

By using these setup, you can have the remote web page (e.g., your script's output) determine the target nodes. Note that the RunDeck JSON format is specific and doesn't report read errors well. Pay close attention to the Rundeck User Guide - Option model provider

If this is not a viable approach, you may need to consider using a different tool such as Jenkins.

0
Niall On

I just had to create a job for a similar purpose - execute a script on a remote node, but pass an arbitrary number of servers to that script. I dumped all the target server names in server.json and am using that as a remote URL in the job's option, "target." The user selects whatever servers from the resulting dropdown, and Run Deck calls the results ${option.target}.

From there, I created an inline script and passed ${option.target} as the args:

#!/bin/env bash 
OPTION_TARGET="$@" 
sudo bash -c "cd /opt/some/directory/bin ; ./script.sh servers=${OPTION_TARGET}"

So Run Deck ultimately dispatches ./script.sh foo bar baz quux on the node I already have tagged, and problem solved. Make sense?

Sorry for the thread necro, but my solution seemed germane.

0
Miroslaw Koniorczyk On

You need to install rundeck-cli command line tool 'rd' which replaced dispatch command mentioned by Istvan.

I). install it from https://rundeck.github.io/rundeck-cli/

$ wget https://bintray.com/rundeck/rundeck-rpm/rpm -O bintray.repo
$ sudo mv bintray.repo /etc/yum.repos.d/
$ sudo yum install rundeck-cli

sudo su - rundeck
mkdir .rd
vim .rd/rd.conf

add those similar lines according to your settings:

-bash-4.2$ cat rd.conf 
export RD_URL=http://localhost:4440
export RD_USER=admin
export RD_PASSWORD=admin

II). Create two Rundeck jobs Job1 and Job2. Both will have two steps:

Job1:Step 1.1 some action against set of nodes option.target defined by tags or list (will be passed to Step 2.1)

than next step will be 'Workflow Steps'/'Job Reference' type, with 'Run as a' set to Workflow Step. It will be another job, to run against localhost and will run also two steps but on rundeck server, locally.

Job1:Step 1.2 'Workflow Step' with argument passed: -targetnodes "${option.target}"

Job2:Step 2.1 option.targetnodes

rd nodes --project {Your project name} --filter ${option.targetnodes} > /tmp/filtered.nodes

and than some script (eg scp some files to local rundeck machine) to iterate over set of nodes from Step 1.1

Job2:Step 2.2

#!/bin/bash

for remoteHost in $(cat /tmp/filtered.nodes | grep -v Nodes | grep -v -e '^[[:space:]]*$')
do
  scp "$remoteHost":/tmp/"$remoteHost".users /tmp/
  echo "$remoteHost".users copied 
done

I did that way because of lack copying from remote to local in Rundeck.