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 and API token.

Before you begin

Ensure that you meet the following prerequisites:

  • You have successfully completed API setup, as described in Setting Up the API.

  • You have Git installed. If not, obtain it from the Git Downloads page.

  • You have local copies of the tutorial samples from GitHub and a local copy of the source code using the git clone command:

    git clone https://github.com/controlm/automation-api-quickstart.git

Begin

  1. Add an environment named prodEnvironment using the environment add command.

    The following command specifies a valid API token, as described in Authentication Service.

    Copy
    ctm environment saas::add prodEnvironment "https://<controlmEndPointHost>/automation-api" "<keyToken>"
  2. Access the tutorial sample with the following command:

    cd automation-api-quickstart/helix-control-m/102-automate-code-deployment

  3. Deploy the code to the prodEnvironment using the deploy command.

    Include the "-e" option in the command to specify a destination environment that differs from the default environment.

    The following example shows a deploy command with a response:

    Copy
    > ctm deploy AutomationAPISampleFlow.json -e prodEnvironment
     
    [
      {
        "deploymentFile": "AutomationAPISampleFlow.json",
        "successfulFoldersCount": 0,
        "successfulSmartFoldersCount": 1,
        "successfulSubFoldersCount": 0,
        "successfulJobsCount": 2,
        "successfulConnectionProfilesCount": 0,
        "successfulDriversCount": 0,
        "isDeployDescriptorValid": false,
        "deployedFolders": [
          "AutomationAPISampleFlow"
        ]
      }
    ]
  4. Retrieve the jobs from the prodEnvironment to a new JSON file named prodEnvironmentJobs.json by running the following deploy jobs::get command:

    Copy
    ctm deploy jobs::get -s "server=*&folder=*" -e prodEnvironment > prodEnvironmentJobs.json
  5. Apply a Deploy Descriptor to the prodEnvironmentJobs.json using the following deploy transform command:

    Copy
    ctm deploy transform prodEnvironmentJobs.json DeployDescriptor.json -e testEnvironment

    The Deploy Descriptor enables you to modify the jobs so that you can deploy them back to your Development environment . The modifications are necessary because the two environments ( prodEnvironment and the Development environment named testEnvironment) differ in their resources. Therefore, the following Deploy Descriptor contains rules to do the following:

    • Modify the Host property value to "devhost" (the host in the Development environment) in any job whose name begins with "Command" or "Script".

    • Add a "Dev" prefix to the Application property for any job in the source code.

    • Set the RunAs user to "devuser".

    Copy
    {
      "DeployDescriptor":
      [  
        {
          "Comment": "Set run as user in Defaults to the Dev automation user",
          "ApplyOn": {
                    "@":"Defaults"
           },
          "Property" :"RunAs",
          "Assign" : "devuser"
        },   
        {
          "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.*" : "devhost"},
                        { "Script.*"  : "devhost"}
          ]
        }
      ]
    }

    The deploy transform command debugs the modifications, and the following output is returned. Note that the name of the application now begins with "Dev", and the two hosts are now "devhost":

    Copy
    {
      "AutomationAPISampleFlow": {
        "Type": "Folder",
        "ControlmServer": "IN01",
        "RunAs": "USERNAME",
        "SubApplication": "SampleSubApp",
        "Application": "DevSampleApp",
        "CommandJob": {
          "Type": "Job:Command",
          "SubApplication": "SampleSubApp",
          "Host": "workbench",
          "RunAs": "USERNAME",
          "Application": "DevSampleApp",
          "Command": "echo my 1st job",
          "When": {
            "WeekDays": [ "MON", "TUE", "WED", "THU", "FRI" ],
            "Months": [ "JAN", "OCT", "DEC" ],
            "MonthDays": [ "1", "11", "22" ],
            "ToTime": "2100",
            "FromTime": "0300"
          },
          "IfBase:Folder:CompletionStatus_0": {
            "Type": "If:CompletionStatus",
            "CompletionStatus": "NOTOK",
            "Mail_0": {
              "Type": "Action:Mail",
              "To": "[email protected]",
              "Message": "%%JOBNAME failed"
            }
          }
        },
        "ScriptJob": {
          "Type": "Job:Script",
          "SubApplication": "SampleSubApp",
          "FileName": "SCRIPT_NAME",
          "Host": "workbench",
          "FilePath": "SCRIPT_PATH",
          "RunAs": "USERNAME",
          "Application": "DevSampleApp",
          "When": {
            "WeekDays": [ "MON", "TUE", "WED", "THU", "FRI" ],
            "Months": [ "JAN", "OCT", "DEC" ],
            "MonthDays": [ "1", "11", "22" ],
            "ToTime": "2100",
            "FromTime": "0300"
          },
          "IfBase:Folder:CompletionStatus_0": {
            "Type": "If:CompletionStatus",
            "CompletionStatus": "NOTOK",
            "Mail_0": {
              "Type": "Action:Mail",
              "To": "[email protected]",
              "Message": "%%JOBNAME failed"
            }
          }
        },
        "Flow": {
          "Type": "Flow",
          "Sequence": [
            "CommandJob",
            "ScriptJob"
          ]
        }
      },
      "JobsRunInDockerSample": {
        "Type": "Folder",
        "ControlmServer": "IN01",
        "RunAs": "controlm",
        "SubApplication": "SampleSubApp",
        "Application": "DevSampleApp",
        "CommandJob": {
          "Type": "Job:Command",
          "SubApplication": "SampleSubApp",
          "Host": "workbench",
          "RunAs": "controlm",
          "Application": "DevSampleApp",
          "Command": "whoami ; pwd; ls -l"
        }
      },
      "AutomationAPIFileTransferDatabaseSampleFlow": {
        "Type": "Folder",
        "Variables": [
          {
            "DestDataFile": "DESTINATION_FILE"
          },
          {
            "SrcDataFile": "SOURCE_FILE"
          }
        ],
        "ControlmServer": "IN01",
        "SubApplication": "SampleSubApp",
        "Application": "DevSampleApp",
        "GetData": {
          "Type": "Job:FileTransfer",
          "ConnectionProfileSrc": "SFTP-CP",
          "ConnectionProfileDest": "Local-CP",
          "SubApplication": "SampleSubApp",
          "Host": "HOST",
          "RunAs": "SFTP-CP+Local-CP",
          "Application": "DevSampleApp",
          "Variables": [
            {
              "DestDataFile": "DESTINATION_FILE"
            },
            {
              "SrcDataFile": "SOURCE_FILE"
            }
          ],
          "FileTransfers": [
            {
              "ABSTIME": "0",
              "VERNUM": "0",
              "Dest": "%%DestDataFile",
              "SRCOPT": "0",
              "TransferType": "Binary",
              "CASEIFS": "0",
              "DSTOPT": "0",
              "RECURSIVE": "0",
              "TransferOption": "SrcToDest",
              "Src": "%%SrcDataFile",
              "TIMELIMIT": "0",
              "EXCLUDE_WILDCARD": "0",
              "NULLFLDS": "0",
              "TRIM": "1",
              "IF_EXIST": "0",
              "UNIQUE": "0",
              "PostCommandDest": {
                "action": "chmod",
                "arg2": "%%DestDataFile",
                "arg1": "700"
              },
              "PreCommandDest": {
                "arg1": "%%DestDataFile",
                "action": "rm"
              }
            }
          ],
          "When": {
            "ToTime": "2100",
            "FromTime": "0300"
          }
        },
        "UpdateRecords": {
          "Type": "Job:Database:SQLScript",
          "SQLScript": "/home/USER/automation-api-quickstart/helix-control-m/101-running-file-transfer-and-database-query-job-flow/processRecords.sql",
          "ConnectionProfile": "DB-CP",
          "SubApplication": "SampleSubApp",
          "Host": "HOST",
          "RunAs": "DB-CP",
          "Application": "DevSampleApp",
          "Variables": [
            {
              "DestDataFile": "DESTINATION_FILE"
            },
            {
              "SrcDataFile": "SOURCE_FILE"
            }
          ],
          "When": {
            "ToTime": "2100",
            "FromTime": "0300"
          }
        },
        "Flow": {
          "Type": "Flow",
          "Sequence": [
            "GetData",
            "UpdateRecords"
          ]
        }
      },
      "JobsRunInDockerSample2": {
        "Type": "Folder",
        "ControlmServer": "IN01",
        "RunAs": "controlm",
        "SubApplication": "SampleSubApp",
        "Application": "DevSampleApp",
        "CommandJob": {
          "Type": "Job:Command",
          "SubApplication": "SampleSubApp",
          "Host": "workbench",
          "RunAs": "controlm",
          "Application": "DevSampleApp",
          "Command": "whoami ; pwd; ls -l"
        }
      }
    }
  6. Use the following deploy command to deploy the jobs to the Development environment while applying the rules from the Deploy Descriptor:

    Copy
    ctm deploy prodEnvironmentJobs.json DeployDescriptor.json -e testEnvironment
  7. Use the following code in Jenkins to push Git changes to Control-M and automate the deployment of Control-M object definitions from the source directory to prodEnvironment:

    Copy
    #!/bin/bash
    for f in *.json; do
     echo "Deploying file $f";
     ctm deploy $f -e prodEnvironment;
    done
  8. Use the following Python script that uses the REST API to automate the deployment of Control-M object definitions from the source directory to prodEnvironment:

    Copy
    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>/automation-api'
    token=<token>
       
    # -----------------
    # Built
    uploaded_files = [
            ('definitionsFile', ('Jobs.json', open('c:\\src\Jobs.json', 'rb'), 'application/json'))
    ]
       
    r = requests.post(endPoint + '/deploy', files=uploaded_files, headers={'x-api-key': + token}, verify=False)
       
    print(r.content)
    print(r.status_code)
       
    exit(r.status_code == requests.codes.ok)