VMware vRealize Automation Cloud Slack Notifications

May 12, 2020

Tweet This:
Share on LinkedIn:

By Dana Gertsch, Kovarus Senior Consultant

This article will cover a basic Slack notification when a deployment fails in VMware vRealize Automation Cloud (vRA Cloud) using an ABX action.

First, the use case.  The operations team wants to know about a failed deployment before they get the ticket or phone call. They are using Slack for team messaging and would like the notification to land there rather than in an email. The message needs to include the failed deployment name, the requestor, and the error message. The proposed solution is to leverage vRA Cloud events to fire an ABX action.

First, set up a development channel and a Slack bot (Application). Doing this is beyond the scope of this article, but it’s well documented here.

You will also need a vRA Cloud API Token. You can get that by going to your vRA Cloud account, clicking on API Tokens, then Generate Token.

Now on to the ABX action. Create a new Python Action under Extensibility, Actions. Add three default inputs (SLACK_CHANNEL, SLACK_API_TOKEN, and VRA CLOUD_REFRESH_TOKEN), and the two dependencies (slackclient and requests).

Now on to the action code.

import json
import logging
import slack
import requests

logger = logging.getLogger()
logger.setLevel(logging.INFO)

VRA CLOUD_API_URL = "https://api.mgmt.cloud.vmware.com"

def handler(context, inputs):
    '''
    Get information about the deployment 
    '''
    deployment_data = {}
    deployment_data["status"] = inputs["status"]
    deployment_data["failureMessage"] = inputs["failureMessage"]
    deployment_data["projectName"] = inputs["projectName"]
    deployment_data["userName"] = inputs["userName"]
    deployment_data["deploymentId"] = inputs["deploymentId"]
    
    ''' 
    get vRA Cloud bearer_token
    work around as the context does not contain auth information for this event
    '''
    bearer_token = get_vRA Cloud_bearer_token(inputs)
    deployment_data["deployment_name"] = get_deployment_name(inputs["deploymentId"], bearer_token)

    '''
    Send to slack bot 
    '''
    slack_result = send_message_to_slack(inputs,deployment_data)
    return slack_result

Within handler, I first get information from the Event Payload and push it into a JSON Object. I did this to reduce the number of inputs when calling ‘send_message_to_slack’ function. Alternatively, I could have just sent inputs and bearer token. Feel free to refactor this if you like.

Here is a partial event payload for your reference.

{
  "status": "FAILED",
  "userName": "dgertsch@kovarus.com",
  "projectName": "redacted",
  "deploymentId": "ee6722da-f8a9-4dd8-9fce-redacted",
  "SLACK_CHANNEL": "#vRA Cloud-development",
  "failureMessage": "Could not find any profile to match network 'Cloud_Network_1' of type 'EXISTING' with constraints '[network:broke-on-purpose]'.",
  "SLACK_API_TOKEN": "redacted",
  "VRA CLOUD_REFRESH_TOKEN": "redacted"
}

Initially I wanted to use the vRA Cloud context to interact with the API. For some reason my calls using context.request failed as I was not authenticated. I know this works as I use it with another Slack notification ABX function. Not to worry, I’ll just do it old fashioned way.

def get_vRA Cloud_bearer_token(inputs):
    url = VRA CLOUD_API_URL + "/iaas/api/login"
    payload = { "refreshToken": inputs["VRA CLOUD_REFRESH_TOKEN"] }
    result = requests.post(url = url, json = payload)
    result_data = result.json()
    bearer_token = result_data["token"]
    # logging.info("### bearer_token is %s ", bearer_token)
    return bearer_token

This bearer token will be used to get the deployment name using the ID in the payload. The returned value is pushed into “development data.”

def get_deployment_name(id, bearer_token):
    url = VRA CLOUD_API_URL + "/deployment/api/deployments/" + id 
    headers = {"Authorization": "Bearer " + bearer_token}
    result = requests.get(url = url, headers=headers)
    logging.info(result)
    result_data = result.json()
    deployment_name = result_data["name"]
    logging.info("### deployment name is %s ", deployment_name)
    return deployment_name

Finally, the data is sent to the Slack. Inputs contains the values for the Slack channel, deployment data, and the Slack API token.

def send_message_to_slack(inputs,deployment_data):
    '''
    Send message to slack bot 
    '''
    SLACK_API_TOKEN = inputs["SLACK_API_TOKEN"]
    SLACK_CHANNEL = inputs["SLACK_CHANNEL"]
    
    logger.info("## Sending message to slack bot ##")
    
    client = slack.WebClient(token=SLACK_API_TOKEN)
    client.chat_postMessage(
      channel=SLACK_CHANNEL,
      blocks=[
        {
          "type": "section",
          "text": {
            "type": "mrkdwn",
            "text": f"*DEPLOYMENT FAILED: *\nDeployment Name: {deployment_data['deployment_name']}"
            }
        },
  {
    "type": "section",
    "text": {
      "type": "mrkdwn",
      "text": "Direct link to broken deployment. "
    },
    "accessory": {
      "type": "button",
      "text": {
        "type": "plain_text",
        "text": "Deployment URL",
      },
      "url": "https://www.mgmt.cloud.vmware.com/deployment-ui/#/deployment/" + deployment_data['deploymentId']
    }
  },          
        {
          "type": "section",
          "fields": [
            {
                "type": "mrkdwn",
                "text": f"*Failure message: *\n{deployment_data['failureMessage']}"
            }
          ]
        },
        {
          "type": "section",
          "fields": [
            {
    "type": "mrkdwn",
    "text": f"*Requested by: *\n{deployment_data['userName']}"
  },            
            {
              "type": "mrkdwn",
              "text": f"*Project: *\n{deployment_data['projectName']}"
            }
          ]
        }
      ]
    )

This action will be called when the deployment fails using an Event Subscription. Create a new subscription, setting the Event Topic to “Deployment completed,” set the condition to ‘event.data.status ==”FAILED”’.

Then select the ABX action you wish to run.

Now to test it. I changed a working blueprint, setting a network tag to something that doesn’t exist. The deployment will fail with the following message.

If everything is setup correctly, you should see a new message in your slack channel.

The Slack message provides the basic information you need to start troubleshooting the deployment failure.

The complete ABX package is available in this github repository.


Looking to learn more about modernizing and automating IT? We created the Kovarus Proven Solutions Center (KPSC) to let you see what’s possible and learn how we can help you succeed. To learn more about the KPSC go to the KPSC page.

Also, follow Kovarus on LinkedIn for technology updates from our experts along with updates on Kovarus news and events.