Deploy Descriptor

Introduction

Control-M Automation API enables you to use Deploy Descriptor to change job definition properties in JSON format before building, deploying, or running the JSON file.

Using the Deploy Descriptor enables you to streamline your code across different environments (for example, between Development, Test, or Production). Since each Control-M environment has different properties, the Deploy Descriptor enables you to programmatically manipulate these properties.

Deploy Descriptor scenarios

The following scenarios are examples of the typical usage of Deploy Descriptors.

Moving from a Test to Production Environment:

In the following example, the Property element defines the job property that is going to be modified. The Deploy Descriptor changes the Control-M/Server to the new value in production using the Assign element and changes the Application and SubApplication to have a "P" (production) prefix instead of "T" (test) using the Replace element. This name change is also applied to folder names, replacing the prefix "T" with a "P".

{
  "DeployDescriptor":
  [
    {
      "Property" :"ControlmServer",
      "Assign" : "ProdControlM"
    },
    {
      "Property" :"Application",
      "Replace" : [ {"T(.*)" : "P$1"} ]
    },
    {
      "Property" :"SubApplication",
      "Replace" : [ {"T(.*)" : "P$1"} ]
    },
    {
      "ApplyOn"     :  {"Type":"Folder"},
      "Property" : "@",
      "Replace" : [ {"T(.*)" : "P$1"} ]
    }
  ]
}

Mapping Jobs to Hosts in Different Environments

Development, Test, and Production environments rarely have the same computer resources, and you might need to distribute the jobs differently between hosts in the different environments.

In this example, we want to change the name of the host on which the job will run to "host1", only if this job is part of the Finance Application.

The Property that we want to change is "Host". The Source is the field to match — in this example, "Application".  When deploying the code file from the Development environment to the Test environment, all jobs belonging to the "Finance" application will be replaced to a single host named "host1".

In the Replace syntax, the value on the left applies to the Source, and the value on the right applies to the Property.

{
"DeployDescriptor":
  [
    {
      "Comment": "Change Host of a Job based on application.",
      "ApplyOn": {"Type":"Job.*"},
      "Property": "Host",
      "Source": "Application",
      "Replace": [ { "Finance.*":"host1"} ]
    }	
  ]
}

In the following example, when deploying the code file from the Test environment to the Production environment, each job is mapped to a different host based on its job name. See JSON path notation for the "@" syntax.

{
"DeployDescriptor":
  [
    {
      "Comment": "Change Host of a Job based on job name.",
      "Property": "Host",
      "ApplyOn" :  {"Type":"Job.*"},
      "Source": "@",
      "Replace": [
    	{ "FinanceJ12":"host1"},
        { "FinanceJ23":"host2"},
        { "FinanceJ45":"host3"} 
		]
    }
	]
}

Moving Back from Production to Development

1. The following command shows how to retrieve the jobs or folders from the Production environment:

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

2. The ProdDefinitions.json file contains the production job definitions. 

In the following example, the Deploy Descriptor modifies the Control-M/Server property to the value in the Development environment using the Assign element and modifies the Application and SubApplication to a "D" prefix (for Development) instead of "P" (for Production) using the Replace element.

The following code example appears in the DeployDescriptor.json file:

{
	"DeployDescriptor":
  [ 	
    {
      "Comment": "Assign Control-M server of a Job.",
      "Property" :"ControlmServer",
      "Assign" : "DevControlM"	
    },
    {
      "Comment": "Change Application of a Job based on its name.",
      "Property" :"Application",
      "Replace" : [ {"P(.*)" : "D$1"} ]
    },
    {
      "Comment": "Change SubApplication of a Job based on its name.",
      "Property" :"SubApplication",
      "Replace" : [ {"P(.*)" : "D$1"} ]	
    }
  ]
}	

The following command enables you to deploy the ProdDefinition.json file to the Development environment using the Deploy Descriptor to change to the development values:

>ctm deploy ProdDefinitions.json DeployDescriptor.json -e development

Debugging and Building the Deploy Descriptor

To debug Deploy Descriptor, use deploy transform to return the JSON jobs definition after processing Deploy Descriptor modifications:

>ctm deploy transform Jobs.json DeployDescriptor.json

To verify that the Deploy Descriptor is valid, you can use build:

>ctm build DeployDescriptor.json

Back to top

Using JSON Path to Locate Attributes

The code elements can be located using JSON Path syntax and the following extensions:

  • "@" - refers to the name of an element for which you can define a custom name; for example, the name of a Job, Folder, or Subfolder, as well as the name of an Event or any other nested object.
  • .parent() - refers to the name of the parent element in the JSON.
  • "." - enables you to navigate between the elements.
    NOTE: If the element name contains a dash "-", use bracket notation instead of dot notation. For example, to locate a job named JOB-NAME in a folder, use $['JOB-NAME'] instead of $.JOB-NAME.

The following example shows "@" that is used to refer to the job name, @.parent() is used to refer to Folder name, and $.PreCommands.FailJobOnCommandFailure allows you to describe a specific job property value:

{
"DeployDescriptor":
  [
  	{
      "ApplyOn" : {
        "Type":"Job",
		"@" : "JobTQ.*",
		"@.parent()" : "FolderTQ.*",
      	"$.PreCommands.FailJobOnCommandFailure" : "True"
      },
      "Property":"Application",
      "Assign": "App1"    
      }
  ]
}

The following example demonstrates a more complex scenario for replacing names of elements for deployment of code from a Test environment to a Production environment, with deep changes in folder and subfolder structure:

{
    "DeployDescriptor": [
    {
        "Comment": "Changes the name of all subfolders to match the production standard",
        "Property": "@",
        "ApplyOn": {
            "Type": "SubFolder"
        },
        "Replace": [{
            "(.*)#(.*)": "Prod$1_$2"
        }]
    },
    {
        "Comment": "Changes the name of dummy jobs to match the production standard",
        "Property": "@",
        "ApplyOn": {
            "Type": "Job:Dummy"
        },
        "Replace": [{
            "(.*)#(.*)": "JOBDummy_$2"
        }]
    },
    {
        "Comment": "Assigns the name of the production ControlmServer to all elements that have this property.",
        "Property": "ControlmServer",
        "Assign": "LocalControlM"
    },
    {
        "Comment": "Assigns the RunAs property to the correct user for all jobs in the folder and subfolders.",
        "Property": "RunAs",
        "Assign": "ctmdk"
    },
    {
        "Comment": "Changes all resources to match the production standard ",
        "Property": "@",
        "ApplyOn": {
            "Type": "Resource.*"
        },
        "Replace": [{
            "TST(.*)": "Prod$1"
        }]
    },
    {
        "Property": "Description",
        "Comment": "Assigns a new description to a specific subfolder.",
        "ApplyOn": {
            "Type": "SubFolder",
            "@": "Folder#3"
        },
        "Assign": "NewDescription"
    }
    ]
}


Back to top

Using Regular Expression Patterns for Matching and Modifying Values

You can use Regular Expressions (regex) to match values of job properties. The following example modifies the names of all Applications that start with "A" by adding "Was" to the current Application name. When using a regex set, use $Number for the ordered matched elements. 

For more information on how to use the ApplyOn filtering, see ApplyOn.

{
 "DeployDescriptor":
  [
     {
        "ApplyOn" : {
        "Application" : "A.*"
      },
      "Property":"Application",
      "Replace": [ {"(.*)" : "Was$1"} ]
	}
  ]
}

Back to top

DeployDescriptor Code Syntax

DeployDescriptor is the root element, and it includes one or more rules. The rules are applied in the order that they appear in the file.

The following example shows how one rule modifies Application name and the next rule evaluates the Application name property that was modified and modifies it once more: 

{
 "DeployDescriptor":
  [
    {
      "Property" :"Application",
      "Replace" : [ {"P(.*)" : "D$1"} ]	
    },
    {
      "Property" :"Application",
      "Replace" : [ {"D(.*)" : "T$1"} ]	
    }
  ]
 }

Back to top

Rule

A rule defines the property to modify and how to modify it.

The rule has two parts:

  • Filter capabilities using the ApplyOn element (optional)
  • Modification capabilities, defined by Property, Assign, Replace, and Source

The following example presents a rule that includes the filter and modification capabilities:

{
      "ApplyOn" : {
        "Comment": "This is the filtering element",
        "Type" : "Job:Hadoop:Spark:Python",
  		"Application" : "a.*"
      },
      "Comment": "The following are the modification elements",
      "Property":"Application",
      "Replace": [ { "(.*)" : "Was$1" } ]
}

Filtering 

ApplyOn

ApplyOn filters the JSON objects to which the rule applies.

The following example shows how ApplyOn is used to filter only jobs that are of type Hadoop Spark Python, in which the Application name starts with "a" and the $.PreCommands.FailJobOnCommandFailure is set to true. 

The rule appends  "Was" to the name of the Application property.

{
"DeployDescriptor":
  [
  	{
      "ApplyOn" : {
      	"Type" : "Job:Hadoop:Spark:Python",
  		"Application" : "a.*",
  		"$.PreCommands.FailJobOnCommandFailure" : "True"
      },
      "Property":"Application",
      "Replace": [ { "(.*)" : "Was$1" } ]
    }
 ]
}

The ApplyOn can filter on multiple properties at once. A single property filter has the following parts:

 Description
NameThe JSON path to locate a property in the definition file

Value

The regular expression for matching the property value

Back to top

Modifying

Property

The Property element specifies the property to update. This element is mandatory.

Property element uses JSON path to locate the property in the definition file.

The following example shows you how to modify the Application property.  

{
 "Property":"Application",
 "Replace": [ { "(.*)" : "Was$1" } ]
}

Assign

Assign enables you to set a new value to the specified PropertyAssign is only used to update an existing property and cannot be used to add a property to an element.

The following example shows how to use Assign, to set SparkScript to "/home/etc/script.py" property in the definitions file.

{
      "Property": "SparkScript",
      "Assign": "/home/etc/script.py"
}

Replace

Replace enables you to modify the value of the specified Property.

Replace contains one or more replacement rules. The first rule that matches the property's original value is applied.

{
 "Property":"Application",
 "Replace": [ { "FNC_JOB15_WIN" : "FNC_JOB15" },
              { "FNC_JOB16_WIN" : "FNC_JOB16" } 
              ]
}

The Replace rule that matches the original value, modifies the Property value using a regular expression mechanism.

The original value is taken from the Property by default.

If Source is defined, the value is taken from the Source. The Source has the following parts:

 Description
Name

The regular expression to match the original value

Value

The regular expression to format the new value

When using a regex set, you can use $Number for the ordered matched elements.

A definition file contains two jobs where the Application property for the first job is "FNC_JOB15_WIN" and "FNC_JOB16_WIN" for the second job.

The following example shows a Replace rule where "FNC_JOB15_WIN" is replaced with "FNC_JOB15" and "FNC_JOB16_WIN" is replaced with "FNC_JOB16":

{
 "Property":"Application",
 "Replace": [ { "FNC_JOB15_WIN" : "FNC_JOB15" },
              { "FNC_JOB16_WIN" : "FNC_JOB16" } 
              ]
}

The following example shows a Replace rule where "FNC_JOB15_WIN" is replaced with "FNC_APP" and "FNC_JOB16_WIN" is replaced with "FNC_APP":

{
 "Property":"Application",
 "Replace": [ { "FNC_.*" : "FNC_APP" } ]
}

The following example shows a Replace rule where "FNC_JOB15_WIN is replaced with "FNC-WIN- JOB15" and "FNC_JOB16_WIN" is replaced with "FNC-WIN-JOB16":

{
 "Property":"Application",
 "Replace": [ { "FNC_(.*)_(.*)" : "FNC-$2-$1" } ]
}

Source

If Source is defined, the Replace original value is taken from the SourceSource value uses JSON path to locate the property in the definition file.

The following example shows how to modify the "Host" property, based on the value of the job name. All job names that start with "Spark" are modified to run on "host1", jobs that start with "MyA" are modified to run on "host2" and all other jobs are modified to run on "host3".

{
  "Property": "Host",
  "Source": "@",
  "Replace": [
    { "Spark.*": "host1"},
    { "MyA.*"  : "host2"},
    { ".*"     : "host3"}
    ]
}

Comment

Allows you to add comments in the Deploy Descriptor JSON. This element is optional.

The following example shows how to add a comment:

{
  "Comment" : "Change the run as property according to the application and the name of the object",
  "ApplyOn" : {
    "$.Application" : "m.*",
    "@" : "F.*1"
  },
  "Property": "RunAs",
  "Assign": "prodUser"
}

Back to top

Related information

For more information about Control-M, use the following resources:

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

Comments