Tutorial - Automating code deployment

This tutorial teaches you how to use a script to automate DevOps tasks. In order to complete this tutorial, you need a valid Control-M endPoint, username, and password.

Before you begin

Ensure that you have set up your environment, as described in Setting up the prerequisites.

Step 1 - Set the Control-M environment

The first task when starting to work with Control-M Automation API is to configure the Control-M environment that you are going to use. An environment is a combination of an endPointusername, and password

An endPoint looks like the following: 

https://<controlmEndPointHost>:8443/automation-api

Let's add an environment and name it ciEnvironment.

The command below shows you how to do this and demonstrates a response:

> ctm environment add ciEnvironment "https://[controlmEndPointHost]:8443/automation-api" "[ControlmUser]" "[ControlmPassword]"
 
info:    Environment 'ciEnvironment' was created
info:    ciEnvironment:
{"endPoint":"https://<controlmEndPointHost>:8443/automation-api","user":"[ControlmUser]"}

You can also deploy to a workbench environment. In such a case, the endpoint is https://localhost:8443/automation-api. The user name and password are both workbench.

Step 2 - Access the tutorial samples

Go to the directory where the tutorial sample is located:

cd automation-api-quickstart/102-automate-code-deployment

Step 3 - Deploy to ciEnvironment

Use the following command to deploy the code to a specific environment. The "-e" is used to specify a destination environment that differs from the default environment.

Note

Ensure that the version of the destination environment matches the version of the CLI.

> ctm deploy AutomationAPISampleFlow.json -e ciEnvironment

[
  {
    "deploymentFile": "AutomationAPISampleFlow.json",
    "successfulFoldersCount": 0,
    "successfulSmartFoldersCount": 1,
    "successfulSubFoldersCount": 0,
    "successfulJobsCount": 2,
    "successfulConnectionProfilesCount": 0,
    "successfulDriversCount": 0,
    "deployedFolders": [
      "AutomationAPISampleFlow"
    ]
  }
]

Step 4 - Retrieve jobs from ciEnvironment back to the Development environment using Deploy Descriptor

You can now retrieve the jobs from the ciEnvironment back to your Development environment (workbench) using a Deploy Descriptor.

The following command shows how to retrieve the jobs and folders from the ciEnvironment in a new JSON file named ciEnvironmentJobs.json:

ctm deploy jobs::get -s "ctm=*&folder=*" -e ciEnvironment > ciEnvironmentJobs.json

Typically, the two environments (in this case, ciEnvironment and the Development environment) differ in their resources. Therefore, in the following example, we will modify the Host property value to "workbench" (the host in the Development environment) in any job whose name begins with "Command" or "Script". In addition, we will add a "Dev" prefix to the Application property for any job in the source code. Finally, we will set the RunAs user to "workbench".

{
  "DeployDescriptor":
  [   
    {
      "Comment": "Set run as user in Defaults to the prod automation user",
      "ApplyOn": {
                "@":"Defaults"
       },
      "Property" :"RunAs",
      "Assign" : "workbench"
    },
    {
      "Comment": "Modify Application property to comply with Development environment",
      "Property" :"Application",
      "Replace" : [ {"(.*)" : "Dev$1"} ]
    },
	{
	  "Comment": "Distribute jobs across hosts available in Development environment based on job names",
	  "Property": "Host",
	  "Source": "@",
	  "Replace": [
					{ "Command.*" : "workbench"},
					{ "Script.*"  : "workbench"}
	  ]
	}
  ]
}

Use the transform command to debug the modifications:

ctm deploy transform ciEnvironmentJobs.json DeployDescriptor.json

The following output is returned. Note that the name of the application now begins with "Dev", and the two hosts are now "workbench":

{
  "Defaults" : {
    "Application" : "DevSampleApp",
    "SubApplication" : "SampleSubApp",
    "RunAs" : "workbench",
    "Job" : {
      "When" : {
        "Months" : [ "JAN", "OCT", "DEC" ],
        "MonthDays" : [ "22", "1", "11" ],
        "WeekDays" : [ "MON", "TUE", "WED", "THU", "FRI" ],
        "FromTime" : "0300",
        "ToTime" : "2100"
      },
      "ActionIfFailure" : {
        "Type" : "If",
        "CompletionStatus" : "NOTOK",
        "mailToTeam" : {
          "Type" : "Mail",
          "Message" : "%%JOBNAME failed",
          "To" : "team@mycomp.com"
        }
      }
    }
  },
  "AutomationAPISampleFlow" : {
    "Type" : "Folder",
    "Comment" : "Code reviewed by John",
    "CommandJob" : {
      "Type" : "Job:Command",
      "Command" : "echo my 1st job",
      "Host" : "workbench"
    },
    "ScriptJob" : {
      "Type" : "Job:Script",
      "FilePath" : "<SCRIPT_PATH>",
      "FileName" : "<SCRIPT_NAME>",
      "Host" : "workbench"
    },
    "Flow" : {
      "Type" : "Flow",
      "Sequence" : [ "CommandJob", "ScriptJob" ]
    }
  }
}

To do the actual deployment to the Development environment, use the following command:

ctm deploy ciEnvironmentJobs.json DeployDescriptor.json -e workbench

Step 5 - Automate deployments

Let's automate the deployment of Control-M object definitions from the source directory to ciEnvironment.

#!/bin/bash
for f in *.json; do
 echo "Deploying file $f";
 ctm deploy $f -e ciEnvironment;
done

This code can be used in Jenkins to push Git changes to Control-M.

Step 6 - Automate deployments with a Python script

You can automate the deployment of Control-M object definitions from the source directory to ciEnvironment with a Python script using the REST API.

import requests  # pip install requests if you don't have it already
import urllib3

urllib3.disable_warnings() # disable warnings when creating unverified requests 
  
endPoint = 'https://<controlmEndPointHost>:8443/automation-api'
  
user = '<ControlMUser>'
passwd = '<ControlMPassword>'
  
# -----------------
# login
r_login = requests.post(endPoint + '/session/login', json={"username": user, "password": passwd}, verify=False)
print(r_login.content)
print(r_login.status_code)
if r_login.status_code != requests.codes.ok:
    exit(1)
  
token = r_login.json()['token']
  
# -----------------
# Built
uploaded_files = [
        ('definitionsFile', ('Jobs.json', open('c:\\src\ctmdk\Jobs.json', 'rb'), 'application/json'))
]
  
r = requests.post(endPoint + '/deploy', files=uploaded_files, headers={'Authorization': 'Bearer ' + token}, verify=False)
  
print(r.content)
print(r.status_code)
  
exit(r.status_code == requests.codes.ok)

Where to go from here

Was this page helpful? Yes No Submitting... Thank you

Comments