Consume vRA SaltStack Config API in vRA Extensibility

These are the early days of the integration between vRealize Automation and vRealize Automation SaltStack Config (formerly know as SaltStack Enterprise) and some things are yet to come. For instance, today in the 8.4 version if you deprovision a VM in vRA the related Salt Minion key is not deleted in vRA SaltStack Config, this a typical situation where a vRA Extensibility elegantly solve the problem.

In order to delete a Salt Minion key we have two options: using the Satl CLI or using the API (RaaS). We have APIs in products for integration and automation purposes and for this reason I picked the second option and here is what I did.

Brief intro about vRA SaltStack API

The API (RaaS) refers to the application server that vRA SaltStack Config clients connect to. These clients include the user interface component of SaltStack Config, properly configured Salt Masters, and other users of RaaS. RaaS is organized into modules (called “resources”) and functions (called “methods”). In the API call test.echo(‘hello, world’), the resource is test and the method is echo(). Arguments can be passed to methods by position or by keyword.

RaaS can be accessed in two ways: via an RPC client and via an HTTP (or HTTPS) bridge:

  • RPC client: The programmatic RPC clients in the sseapiclient Python module work with Python version 2.7 and Python version 3.5 or later. The clients connect to vRA SaltStack Config via HTTP or HTTPS and authenticate.
  • HTTP Bridge: The HTTP (or HTTPS) bridge accepts JSON payloads POSTed to an endpoint exposed by vRA SaltStack Config, translates the payloads into RPC calls, then returns the result as JSON. The endpoint supports cookie-based authentication so that authentication credentials need to be passed only once per session.

For me, the RPC client proved to be definitely easier to use than the HTTP bridge.

Use SaltStack RPC in vRO Workflows

vRealize Automation since version 8.0 supports two types of extensibilities: vRO Workflows and ABX Actions, both supports Python (required by the RPC Client). In this post I am going to cover the vRO Workflow option.

Prepare you local dev environment

I tried this first on my Mac, but I had some issues and after some unsuccessful troubleshooting I opted to do the dev activity on an Ubuntu 20.04 box. You need to prepare your dev environment as follows:

Have both Python 3 and Pip installed on your machine:

sudo apt update
sudo apt install python3.8
sudo apt install python3-pip

Create a directory to store all your artifacts, you can choose any name that works for you:

mkdir /p ~/code/vro_ssc_delete_minion

In your dev directory create a new directory named lib, the name have to be lib as in this directory you will install all the python script dependencies and vRO will look for this specific directory name for dependencies.

mkdir ~/code/vro_ssc_delete_minion/lib

Download from the API Client (Products and Account > Products > All Products and search for SaltStack keyword), as I am working with vRA 8.4 I got the following file vRA_SSEAPE-8.4.0-py2.py3-none-any.whl, once downloaded copy it in your dev folder and then install it the lib folder. As I was prompted to do so, I also installed the package named six.

mv /tmp/SSEAPE-8.4.0-py2.py3-none-any.whl ~/code/vro_ssc_delete_minion
cd ~/code/vro_ssc_delete_minion
python3 -m pip install SSEAPE-8.4.0-py2.py3-none-any.whl -t ./lib
python3 -m pip install six -t ./lib

Create the package with your Python script

Add to your dev folder the Python script that uses the API Client, here below there is my script (you can do a better script for sure with error handling and so on). In my script there is just a thing to note: to delete a Minion from SaltStack Config you need to know its key, in my environment I use the machine IP address as the Minion key, this is provided as an input to the script. In my case I have this script in a file named

from sseapiclient import APIClient

def handler(context, inputs):
    outputs = {}
    minion_key = inputs["addresses"]
    msg = "The address is: {0}!".format(minion_key)

    #connection info
    ssc_host = 'https://vrassc.iberia.local'
    username = '<<USERNAME>>'
    password = '<<PASSWORD>>'
    client = APIClient(ssc_host, username, password, ssl_validate_cert=False)
    client.minion.set_minion_key_state(state='delete', minions=['salt',minion_key])


    return outputs

Zip the content of the dev folder (you can remove the SSEAPE-8.4.0-py2.py3-none-any.whl file).

zip -r ~/ .

Create the vRO Workflow

As first thing you need to create a new Action that uses your Python script. Pick an existing Module, or create a new one (my Module is named, click the “New Action” button, provide Action names (in my case deleteMinion) and other details (I always recommend to add a description) and then select the Script tab. Here you have to choose Runtime = Python 3.7 and Type = Zip, at this point a “Import” button should appear allowing you to upload your zip package including your Python script. In the “Entry handler” text field you have to type the name of the script file without extension followed by a dot and the word “handler”, in my case I have vro_ssc_delete_minion.handler. At this stage you should be as in the situation in the picture below.

Now you have to hit on the “Add New Input button” and add a new string input named minionKey. Do not forget a description before clicking on the Create button.

Now you can create your new Workflow that will be used into a extensibility subscription. Pick a folder in vRO Library and add a new workflow, give it a name (in my vase IBSE SSC Delete Minion Key) and other details (e.g. description). Add a input named inputProperties and Type Properties, add two variables: minionKey having Type String and actionResult having Type Properties.

My workflow schema is made up by 3 elements in this order: a Scriptable Task named Read from vRA, the action we just created named deleteMinion and a Scriptable Task named Log Output.

Details about the Read from vRA Scriptable Task:

  • Inputs: inputProperties
  • Output: none.
  • The script is here below:
var pProperties = new Array();
minionKey = "";
//Looking for 'minion ID key' as IP address of the VM (this is my specific setting)
pProperties = inputProperties.get("addresses");

if (pProperties[0] != null && pProperties[0] != ""){
    minionKey = String(pProperties[0]);
    System.log("Minion ID found: " +minionKey);

Details about the deleteMinion Action:

  • Inputs: minionKey
  • Output: actionResult

Details about the Log Output Scriptable Task:

  • Inputs: actionResult
  • Output: none
  • The script is here below:
System.log("Action result: "+actionResult["greetings"])

Configure the Extensibility Subscription

In the vRealize Automation Cloud Assembly navigate to Extensibility tab and add a new Subscription with the following specifics:

  • Event topic: Compute post removal
  • Condition: == '<your clout template ID>'
  • Action/Workflow: IBSE SSC Delete Minion Key

In my case the subscription condition binds the execution of the extensibility for a specific Cloud Template (aka blueprint), in my case this Cloud Template deploys a VM and registers it as a Minion under vRA SaltStack Config. You may need to change this condition in case you need to execute the extensibility under different scenario.


When a VM or an entire deployment based on the Cloud Template specified in the condition is deleted the extensibility is executed.

The workflow executes the SaltStack Config API and the Minion Key is deleted.